blob: 6eeb59dccc40845b39335c1c8372bc713dc10e9f [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2021 the Eclipse BaSyx Authors
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
******************************************************************************/
package org.eclipse.basyx.testsuite.regression.submodel.metamodel.map.submodelelement.operation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Function;
import org.eclipse.basyx.submodel.metamodel.api.qualifier.haskind.ModelingKind;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IAsyncInvocation;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperation;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperationVariable;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElement;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.OperationExecutionErrorException;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.OperationExecutionTimeoutException;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.OperationVariable;
import org.eclipse.basyx.vab.exception.provider.WrongNumberOfParametersException;
import org.junit.Before;
import org.junit.Test;
/**
* Tests for IOperation
*
* @author conradi
*
*/
public abstract class TestOperationSuite {
protected static final String IN_VALUE = "inValue";
protected static final String OUT_VALUE = "outValue";
protected static final String INOUT_VALUE = "inOutValue";
protected static Collection<OperationVariable> IN;
protected static Collection<OperationVariable> OUT;
protected static Collection<OperationVariable> INOUT;
protected static final Function<Object[], Object> FUNC = (Function<Object[], Object>) v -> {
return (int)v[0] + (int)v[1];
};
protected static final Function<Object[], Object> EXCEPTION_FUNC = (Function<Object[], Object>) v -> {
throw new NullPointerException();
};
protected IOperation operation;
protected IOperation operationException;
/**
* Converts an Operation into the IOperation to be tested
*/
protected abstract IOperation prepareOperation(Operation operation);
@Before
public void setup() {
IN = new ArrayList<OperationVariable>();
OUT = new ArrayList<OperationVariable>();
INOUT = new ArrayList<OperationVariable>();
Property inProp1 = new Property("testIn1", IN_VALUE);
inProp1.setModelingKind(ModelingKind.TEMPLATE);
Property inProp2 = new Property("testIn2", IN_VALUE);
inProp2.setModelingKind(ModelingKind.TEMPLATE);
Property outProp = new Property("testId2", OUT_VALUE);
outProp.setModelingKind(ModelingKind.TEMPLATE);
Property inOutProp = new Property("testId3", INOUT_VALUE);
inOutProp.setModelingKind(ModelingKind.TEMPLATE);
IN.add(new OperationVariable(inProp1));
IN.add(new OperationVariable(inProp2));
OUT.add(new OperationVariable(outProp));
INOUT.add(new OperationVariable(inOutProp));
Operation op1 = new Operation(IN, OUT, INOUT, FUNC);
op1.setIdShort("op1");
operation = prepareOperation(op1);
Operation op2 = new Operation(IN, OUT, INOUT, EXCEPTION_FUNC);
op2.setIdShort("op2");
operationException = prepareOperation(op2);
}
@Test
public void testInvoke() throws Exception {
assertEquals(5, operation.invoke(2, 3));
}
@Test
public void testInvokeException() throws Exception {
try {
// Ensure the operation is invoked directly
operationException.invoke(1, 2);
fail();
} catch (Exception e) {
// Exceptions from ConnectedOperation are wrapped in ProviderException
assertTrue(e instanceof NullPointerException
|| e.getCause() instanceof NullPointerException);
}
}
@Test
public void testInvokeWithSubmodelElements() {
Property param1 = new Property("testIn1", 2);
param1.setModelingKind(ModelingKind.TEMPLATE);
Property param2 = new Property("testIn2", 4);
param2.setModelingKind(ModelingKind.TEMPLATE);
SubmodelElement[] result = operation.invoke(param1, param2);
assertEquals(1, result.length);
assertEquals(6, result[0].getValue());
}
@Test
public void testInvokeParametersException() throws Exception {
try {
operation.invoke(1);
fail();
} catch (Exception e) {
// Exceptions from ConnectedOperation are wrapped in ProviderException
assertTrue(e instanceof WrongNumberOfParametersException
|| e.getCause() instanceof WrongNumberOfParametersException);
}
}
@Test
public void testInvokeAsync() throws Exception {
AsyncOperationHelper helper = new AsyncOperationHelper();
IOperation operation = prepareOperation(helper.getAsyncOperation());
IAsyncInvocation invocation = operation.invokeAsync(3, 2);
assertFalse(invocation.isFinished());
helper.releaseWaitingOperation();
assertTrue(invocation.isFinished());
assertEquals(5, invocation.getResult());
}
@Test
public void testInvokeMultipleAsync() throws Exception {
AsyncOperationHelper helper = new AsyncOperationHelper();
IOperation operation = prepareOperation(helper.getAsyncOperation());
IAsyncInvocation invocation1 = operation.invokeAsync(1, 2);
IAsyncInvocation invocation2 = operation.invokeAsync(6, 2);
assertFalse(invocation1.isFinished());
assertFalse(invocation2.isFinished());
helper.releaseWaitingOperation();
assertTrue(invocation1.isFinished());
assertTrue(invocation2.isFinished());
assertEquals(3, invocation1.getResult());
assertEquals(8, invocation2.getResult());
}
@Test
public void testInvokeAsyncTimeout() throws Exception {
AsyncOperationHelper helper = new AsyncOperationHelper();
IOperation operation = prepareOperation(helper.getAsyncOperation());
// timeout of 1ms
IAsyncInvocation invocation = operation.invokeAsyncWithTimeout(1, 3, 2);
// Should be more than enough to trigger the timeout exception
Thread.sleep(100);
helper.releaseWaitingOperation();
assertTrue(invocation.isFinished());
try {
invocation.getResult();
fail();
} catch (OperationExecutionTimeoutException e) {
}
}
@Test
public void testInvokeExceptionAsync() throws Exception {
AsyncOperationHelper helper = new AsyncOperationHelper();
IOperation operationException = prepareOperation(helper.getAsyncExceptionOperation());
IAsyncInvocation invocation = operationException.invokeAsync();
assertFalse(invocation.isFinished());
helper.releaseWaitingOperation();
try {
invocation.getResult();
fail();
} catch (OperationExecutionErrorException e) {
}
}
@Test
public void testInputVariables() {
Collection<IOperationVariable> inputVariables = operation.getInputVariables();
assertEquals(2, inputVariables.size());
Object value = getValueFromOpVariable(inputVariables);
assertEquals(IN_VALUE, value);
}
@Test
public void testOutputVariables() {
Collection<IOperationVariable> outputVariables = operation.getOutputVariables();
assertEquals(1, outputVariables.size());
Object value = getValueFromOpVariable(outputVariables);
assertEquals(OUT_VALUE, value);
}
@Test
public void testInOutputVariables() {
Collection<IOperationVariable> inoutVariables = operation.getInOutputVariables();
assertEquals(1, inoutVariables.size());
Object value = getValueFromOpVariable(inoutVariables);
assertEquals(INOUT_VALUE, value);
}
/**
* Gets the Value from the OperationVariable in a collection
*/
private Object getValueFromOpVariable(Collection<IOperationVariable> vars) {
IOperationVariable var = new ArrayList<>(vars).get(0);
return var.getValue().getValue();
}
}