/**
* Copyright (c) 2015 committers of YAKINDU and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* Contributors:
* committers of YAKINDU - initial API and implementation
*
*/
package org.yakindu.sct.model.stext.test;
import static org.junit.Assert.fail;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.yakindu.base.expressions.expressions.Expression;
import org.yakindu.sct.model.stext.expressions.STextExpressionParser.LinkingException;
import org.yakindu.sct.model.stext.scoping.ContextPredicateProvider;
import org.yakindu.sct.model.stext.stext.LocalReaction;
import org.yakindu.sct.model.stext.stext.ReactionEffect;
import org.yakindu.sct.model.stext.stext.ReactionTrigger;
import org.yakindu.sct.model.stext.stext.VariableDefinition;
import org.yakindu.sct.model.stext.test.util.AbstractSTextTest;
import org.yakindu.sct.model.stext.test.util.STextInjectorProvider;
/**
* @author andreas muelder - Initial contribution and API
* @author Johannes Dicks - Add tests covering {@link ContextPredicateProvider}
*/
@RunWith(Parameterized.class)
public class STextScopeProviderTest extends AbstractSTextTest {
public static final String INTERNAL_SCOPE = "" + //
"internal: " + //
" in event e1 : void" + //
" in event e2 : void" + //
" var myInt : integer" + //
" var myBool : boolean" + //
" operation myOpp(param1 : integer) : void" + //
" operation myOpp3() : integer" + //
" operation myOpp4() : boolean" + //
" operation myOpp5() : integer";
public static final String INTERFACE_SCOPE = "" + //
"interface Interface1:" + //
" in event e3 : void" + //
" in event e4 : void" + //
" var myInt2 : integer" + //
" var myBool2 : boolean" + //
" operation myOpp2(param1 : integer) : void";
public static final String INTERFACE_SCOPE_AND_INTERNAL_SCOPE = INTERNAL_SCOPE + "\n" + INTERFACE_SCOPE;
private String statement;
private String ruleName;
private String scopes;
private boolean isLinkable;
public STextScopeProviderTest(String statement, String ruleName, String scopes, Boolean isLinkable) {
this.statement = statement;
this.ruleName = ruleName;
this.scopes = scopes;
this.isLinkable = isLinkable;
STextInjectorProvider provider = new STextInjectorProvider();
provider.getInjector().injectMembers(this);
}
@Test
public void test() {
try {
parseExpression(statement, ruleName, scopes);
if (!isLinkable)
fail(String.format(
"Expected not to be linkable [parse '%s' in rule '%s' for scope '%s' expected linkable = '%s']",
statement, ruleName, scopes, isLinkable));
} catch (LinkingException e) {
if (isLinkable)
throw new RuntimeException("Expected linkable but : "+e.getMessage(),e);
}
}
/**
* @see {@link ContextPredicateProvider#filter}
*/
@Parameters(name = "{index}: {0} in rule {1} expected to be invalid = {3}")
public static Iterable<Object[]> data1() {
return Arrays.asList(new Object[][] { //
/* testGuardScopingSuccess */
{ "[e1]", ReactionTrigger.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "[Interface1.e3]", ReactionTrigger.class.getSimpleName(), INTERFACE_SCOPE, true }, //
{ "[e1 && e2]", ReactionTrigger.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "[e1 && Interface1.e3]", ReactionTrigger.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "[Interface1.e4 && Interface1.e3]", ReactionTrigger.class.getSimpleName(), INTERFACE_SCOPE, true }, //
/*
* filter.put(key(ASSIGNMENT_EXPRESSION),
* VARIABLES_OPERATIONS_EVENTS_ENUMERATORS)
*/
{ "myInt = 0", ReactionEffect.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myInt = Interface1.myInt2", ReactionEffect.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "myInt = myOpp3()", ReactionEffect.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myBool = e1", ReactionEffect.class.getSimpleName(), INTERNAL_SCOPE, true }, //
/*
* filter.put(key(CONDITIONAL_EXPRESSION),
* VARIABLES_AND_OPERATIONS)
*/
{ "myBool ? myOpp(1) : myOpp(2)", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myOpp4() ? myInt : myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, true}, //
{ "myBool ? e1 : myOpp(2)", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
/*
* filter.put(key(LOGICAL_OR_EXPRESSION),
* VARIABLES_OPERATIONS_EVENTS_ENUMERATORS)
*/
{ "myBool || Interface1.myBool2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "myBool || myOpp4()", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myBool || e1", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
/*
* filter.put(key(LOGICAL_AND_EXPRESSION),
* VARIABLES_OPERATIONS_EVENTS_ENUMERATORS)
*/
{ "myBool && Interface1.myBool2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "myBool && myOpp4()", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myBool && e1", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
/*
* filter.put(key(BITWISE_XOR_EXPRESSION), VARIABLES)
*/
{ "myInt ^ Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "e1 ^ e2", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
{ "myOpp(1) ^ myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
/*
* filter.put(key(BITWISE_OR_EXPRESSION), VARIABLES)
*/
{ "myInt | Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "e1 | e2", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
{ "myOpp(1) | myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
/*
* filter.put(key(BITWISE_AND_EXPRESSION), VARIABLES)
*/
{ "myInt & Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "e1 & e2", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
{ "myOpp(1) & myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
/*
* filter.put(key(SHIFT_EXPRESSION), VARIABLES)
*/
{ "myInt << Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "myInt >> Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "e1 >> e2", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
{ "e1 >> e2", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
{ "myOpp(1) >> myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
{ "myOpp(1) << myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
/*
* filter.put(key(LOGICAL_NOT_EXPRESSION),
* VARIABLES_OPERATIONS_EVENTS_ENUMERATORS)
*/
{ "!Interface1.myBool2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE, true }, //
{ "!myOpp4()", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "!e1", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
/*
* filter.put(key(LOGICAL_RELATION_EXPRESSION),
* VARIABLES_OPERATIONS_EVENTS_ENUMERATORS)
*/
{ "myInt < Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "myInt < myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myInt > Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "myInt > myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myInt <= Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "myInt <= myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myInt >= Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "myInt >= myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myInt == Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "myInt == myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myInt != Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "myInt != myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
/*
* filter.put(key(NUMERICAL_ADD_SUBTRACT_EXPRESSION),
* VARIABLES_AND_OPERATIONS)
*/
{ "myInt + Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "myInt - Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "myOpp3() + myInt", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myInt - myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myOpp3() + myInt", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myOpp3() - myInt", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "e1 + e2", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
{ "e1 - e2", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
/*
* filter.put(key(NUMERICAL_MULTIPLY_DIVIDE_EXPRESSION),
* VARIABLES_AND_OPERATIONS)
*/
{ "myInt * Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "myInt / Interface1.myInt2", Expression.class.getSimpleName(), INTERFACE_SCOPE_AND_INTERNAL_SCOPE,
true }, //
{ "myOpp3() * myInt", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myInt / myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "myOpp3() * myInt", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "e1 * e2", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
{ "e1 / e2", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
/*
* filter.put(key(NUMERICAL_UNARY_EXPRESSION),
* VARIABLES_AND_OPERATIONS)
*/
{ "-myInt", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "+myInt", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "-myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "+myOpp3()", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
{ "-e1", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
{ "+e1", Expression.class.getSimpleName(), INTERNAL_SCOPE, false }, //
/*
* filter.put(key(EVENT_VALUE_REFERENCE_EXPRESSION), EVENTS)
*/
{ "valueof(e2)", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, //
// { "valueof(myInt)", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, // context predicates can't validate this expression. This will be done in the SText validation instead.
// { "valueof(myOpp3())", Expression.class.getSimpleName(), INTERNAL_SCOPE, true }, // context predicates can't validate this expression. This will be done in the SText validation instead.
/*
* filter.put(key(VARIABLE_DEFINITION, TYPED_ELEMENT__TYPE),
* TYPES)
*/
{ "var x : integer", VariableDefinition.class.getSimpleName(), INTERNAL_SCOPE, true }, //
/* filter.put(key(REGULAR_EVENT_SPEC), EVENTS) */
{ "e1 / myInt = 0", LocalReaction.class.getSimpleName(), INTERNAL_SCOPE, true }, //
//{ "myOpp(4) / myInt = 10", LocalReaction.class.getSimpleName(), INTERNAL_SCOPE, true }, // context predicates can't validate this expression. This will be done in the SText validation instead.
//{ "myInt / myInt = 10", LocalReaction.class.getSimpleName(), INTERNAL_SCOPE, true }, // context predicates can't validate this expression. This will be done in the SText validation instead.
});
}
}