瀏覽代碼

OCB interfaces should be checked for null in enter() method (#1702)

* added exception for unimplemented OCBs

* added exception for unimplemented internal OCBs

* formatting

* added java test for unimplemented OCBs
rherrmannr 7 年之前
父節點
當前提交
146ee8ca9e

+ 14 - 0
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/Statemachine.xtend

@@ -31,6 +31,7 @@ import static org.eclipse.xtext.util.Strings.*
 import org.yakindu.base.types.Event
 import java.util.Set
 import java.util.TreeSet
+import org.yakindu.sct.model.stext.stext.OperationDefinition
 
 class Statemachine {
 	
@@ -633,6 +634,19 @@ class Statemachine {
 				throw new IllegalStateException("timer not set.");
 			}
 			«ENDIF»
+			«IF flow.internalScope !== null && flow.internalScope.hasOperations»
+				if (this.operationCallback == null) {
+					throw new IllegalStateException("Operation callback for internal must be set.");	
+				}
+			«ENDIF»
+			«FOR scope : flow.interfaceScopes»
+				«IF scope.hasOperations»
+					if (this.«scope.interfaceName.asEscapedIdentifier».operationCallback == null) {
+						throw new IllegalStateException("Operation callback for interface «scope.interfaceName.asEscapedIdentifier» must be set.");
+					}
+					
+				«ENDIF»
+			«ENDFOR»
 			«enterSequences.defaultSequence.code»
 		}
 

+ 43 - 0
test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/src/operationcallbackimpl/IOperationCallbackImplStatemachine.java

@@ -0,0 +1,43 @@
+package org.yakindu.src.operationcallbackimpl;
+
+import org.yakindu.scr.IStatemachine;
+
+public interface IOperationCallbackImplStatemachine extends IStatemachine {
+
+	public interface InternalOperationCallback {
+	
+		public void operation1();
+		
+	}
+	
+	public void setInternalOperationCallback(InternalOperationCallback operationCallback);
+	
+	public interface SCInterface {
+	
+		public void setSCInterfaceOperationCallback(SCInterfaceOperationCallback operationCallback);
+	
+	}
+	
+	public interface SCInterfaceOperationCallback {
+	
+		public void operation2();
+		
+	}
+	
+	public SCInterface getSCInterface();
+	
+	public interface SCINamed {
+	
+		public void setSCINamedOperationCallback(SCINamedOperationCallback operationCallback);
+	
+	}
+	
+	public interface SCINamedOperationCallback {
+	
+		public void operation3();
+		
+	}
+	
+	public SCINamed getSCINamed();
+	
+}

+ 12 - 0
test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/src/operationcallbackimpl/InterfaceOCBImpl.java

@@ -0,0 +1,12 @@
+package org.yakindu.src.operationcallbackimpl;
+
+
+import org.yakindu.src.operationcallbackimpl.IOperationCallbackImplStatemachine.SCInterfaceOperationCallback;
+
+public class InterfaceOCBImpl implements SCInterfaceOperationCallback{
+
+	@Override
+	public void operation2() {		
+	}
+
+}

+ 11 - 0
test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/src/operationcallbackimpl/InternalOCBImpl.java

@@ -0,0 +1,11 @@
+package org.yakindu.src.operationcallbackimpl;
+
+import org.yakindu.src.operationcallbackimpl.IOperationCallbackImplStatemachine.InternalOperationCallback;
+
+public class InternalOCBImpl implements InternalOperationCallback{
+
+	@Override
+	public void operation1() {
+	}
+
+}

+ 11 - 0
test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/src/operationcallbackimpl/NamedInterfaceOCBImpl.java

@@ -0,0 +1,11 @@
+package org.yakindu.src.operationcallbackimpl;
+
+import org.yakindu.src.operationcallbackimpl.IOperationCallbackImplStatemachine.SCINamedOperationCallback;
+
+public class NamedInterfaceOCBImpl implements SCINamedOperationCallback{
+
+	@Override
+	public void operation3() {		
+	}
+
+}

+ 188 - 0
test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/src/operationcallbackimpl/OperationCallbackImplStatemachine.java

@@ -0,0 +1,188 @@
+package org.yakindu.src.operationcallbackimpl;
+
+import org.yakindu.scr.conditionalexpressions.ConditionalExpressionsStatemachine.State;
+
+public class OperationCallbackImplStatemachine implements IOperationCallbackImplStatemachine {
+
+	protected class SCInterfaceImpl implements SCInterface {
+	
+		private SCInterfaceOperationCallback operationCallback;
+		
+		public void setSCInterfaceOperationCallback(
+				SCInterfaceOperationCallback operationCallback) {
+			this.operationCallback = operationCallback;
+		}
+	}
+	
+	protected SCInterfaceImpl sCInterface;
+	
+	protected class SCINamedImpl implements SCINamed {
+	
+		private SCINamedOperationCallback operationCallback;
+		
+		public void setSCINamedOperationCallback(
+				SCINamedOperationCallback operationCallback) {
+			this.operationCallback = operationCallback;
+		}
+	}
+	
+	protected SCINamedImpl sCINamed;
+	
+	private boolean initialized = false;
+	
+	public enum State {
+		main_region_StateA,
+		$NullState$
+	};
+	
+	private final State[] stateVector = new State[1];
+	
+	private int nextStateIndex;
+	
+	
+	
+	private InternalOperationCallback operationCallback;
+	public OperationCallbackImplStatemachine() {
+		sCInterface = new SCInterfaceImpl();
+		sCINamed = new SCINamedImpl();
+	}
+	
+	public void init() {
+		this.initialized = true;
+		for (int i = 0; i < 1; i++) {
+			stateVector[i] = State.$NullState$;
+		}
+		clearEvents();
+		clearOutEvents();
+	}
+	
+	public void enter() {
+		if (!initialized) {
+			throw new IllegalStateException(
+					"The state machine needs to be initialized first by calling the init() function.");
+		}
+		if (this.operationCallback == null) {
+			throw new IllegalStateException("Operation callback for internal must be set.");	
+		}
+		if (this.sCInterface.operationCallback == null) {
+			throw new IllegalStateException("Operation callback for interface sCInterface must be set.");
+		}
+		
+		if (this.sCINamed.operationCallback == null) {
+			throw new IllegalStateException("Operation callback for interface sCINamed must be set.");
+		}
+		
+		enterSequence_main_region_default();
+	}
+	
+	public void exit() {
+		exitSequence_main_region();
+	}
+	
+	/**
+	 * @see IStatemachine#isActive()
+	 */
+	public boolean isActive() {
+		return stateVector[0] != State.$NullState$;
+	}
+	
+	/** 
+	* Always returns 'false' since this state machine can never become final.
+	*
+	* @see IStatemachine#isFinal()
+	*/
+	public boolean isFinal() {
+		return false;
+	}
+	/**
+	* This method resets the incoming events (time events included).
+	*/
+	protected void clearEvents() {
+	}
+	
+	/**
+	* This method resets the outgoing events.
+	*/
+	protected void clearOutEvents() {
+	}
+	
+	/**
+	* Returns true if the given state is currently active otherwise false.
+	*/
+	public boolean isStateActive(State mainRegionA) {
+	
+		switch (mainRegionA) {
+		case main_region_StateA:
+			return stateVector[0] == State.main_region_StateA;
+		default:
+			return false;
+		}
+	}
+	
+	public SCInterface getSCInterface() {
+		return sCInterface;
+	}
+	
+	public SCINamed getSCINamed() {
+		return sCINamed;
+	}
+	
+	public void setInternalOperationCallback(
+			InternalOperationCallback operationCallback) {
+		this.operationCallback = operationCallback;
+	}
+	
+	/* 'default' enter sequence for state StateA */
+	private void enterSequence_main_region_StateA_default() {
+		nextStateIndex = 0;
+		stateVector[0] = State.main_region_StateA;
+	}
+	
+	/* 'default' enter sequence for region main region */
+	private void enterSequence_main_region_default() {
+		react_main_region__entry_Default();
+	}
+	
+	/* Default exit sequence for state StateA */
+	private void exitSequence_main_region_StateA() {
+		nextStateIndex = 0;
+		stateVector[0] = State.$NullState$;
+	}
+	
+	/* Default exit sequence for region main region */
+	private void exitSequence_main_region() {
+		switch (stateVector[0]) {
+		case main_region_StateA:
+			exitSequence_main_region_StateA();
+			break;
+		default:
+			break;
+		}
+	}
+	
+	/* The reactions of state StateA. */
+	private void react_main_region_StateA() {
+	}
+	
+	/* Default react sequence for initial entry  */
+	private void react_main_region__entry_Default() {
+		enterSequence_main_region_StateA_default();
+	}
+	
+	public void runCycle() {
+		if (!initialized)
+			throw new IllegalStateException(
+					"The state machine needs to be initialized first by calling the init() function.");
+		clearOutEvents();
+		for (nextStateIndex = 0; nextStateIndex < stateVector.length; nextStateIndex++) {
+			switch (stateVector[nextStateIndex]) {
+			case main_region_StateA:
+				react_main_region_StateA();
+				break;
+			default:
+				// $NullState$
+			}
+		}
+		clearEvents();
+	}
+}

+ 1 - 1
test-plugins/org.yakindu.sct.generator.java.test/src/org/yakindu/sct/generator/java/test/AllTestsTestCustom.java

@@ -17,6 +17,6 @@ import org.yakindu.sct.generator.java.JavaSCTGeneratorTest;
 
 @RunWith(Suite.class)
 @SuiteClasses({ OperationsTestCustom.class, OperationsWithoutBracesCustom.class, JavaSCTGeneratorTest.class,
-		WrapperTest.class, VariadicOperationsTestCustom.class })
+		WrapperTest.class, VariadicOperationsTestCustom.class, UnimplementedOCBTest.class})
 public class AllTestsTestCustom {
 }

+ 64 - 0
test-plugins/org.yakindu.sct.generator.java.test/src/org/yakindu/sct/generator/java/test/UnimplementedOCBTest.java

@@ -0,0 +1,64 @@
+package org.yakindu.sct.generator.java.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.yakindu.src.operationcallbackimpl.InterfaceOCBImpl;
+import org.yakindu.src.operationcallbackimpl.InternalOCBImpl;
+import org.yakindu.src.operationcallbackimpl.NamedInterfaceOCBImpl;
+import org.yakindu.src.operationcallbackimpl.OperationCallbackImplStatemachine;
+import org.yakindu.src.operationcallbackimpl.OperationCallbackImplStatemachine.State;
+
+public class UnimplementedOCBTest {
+	
+	private OperationCallbackImplStatemachine statemachine;
+	
+	@Rule
+	public ExpectedException exceptions = ExpectedException.none();
+	
+	@Before
+	public void setUp() {
+		statemachine = new OperationCallbackImplStatemachine();
+		statemachine.init();
+	}
+	
+	@Test
+	public void testUnimplementedInternal() throws IllegalStateException{		
+		exceptions.expect(IllegalStateException.class);
+		exceptions.expectMessage("Operation callback for internal must be set.");
+		statemachine.enter();
+	}
+	
+	@Test
+	public void testUnimplementedInterfacce() {
+		statemachine.setInternalOperationCallback(new InternalOCBImpl()); 
+		
+		exceptions.expect(IllegalStateException.class);
+		exceptions.expectMessage("Operation callback for interface sCInterface must be set.");
+		
+		statemachine.enter();
+	}
+	
+	@Test
+	public void testUnimplementedNamedInterface() {
+		statemachine.setInternalOperationCallback(new InternalOCBImpl());
+		statemachine.getSCInterface().setSCInterfaceOperationCallback(new InterfaceOCBImpl());
+
+		exceptions.expect(IllegalStateException.class);
+		exceptions.expectMessage("Operation callback for interface sCINamed must be set.");
+		
+		statemachine.enter();
+	}
+	
+	@Test
+	public void testImplementedOCBs(){
+		statemachine.setInternalOperationCallback(new InternalOCBImpl());
+		statemachine.getSCInterface().setSCInterfaceOperationCallback(new InterfaceOCBImpl());
+		statemachine.getSCINamed().setSCINamedOperationCallback(new NamedInterfaceOCBImpl());
+		statemachine.enter();
+		assertTrue(statemachine.isStateActive(State.main_region_StateA));
+	}
+}