Pārlūkot izejas kodu

Added generator for gunit testcases and container junit tests.

markus.muehlbrandt@gmail.com 13 gadi atpakaļ
vecāks
revīzija
b69bc528d1
28 mainītis faili ar 1256 papildinājumiem un 3 dzēšanām
  1. 16 0
      plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/GeneratorExecutor.java
  2. 2 1
      plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/impl/AbstractSGraphModelGenerator.java
  3. 1 0
      test-plugins/org.yakindu.sct.generator.c.test/.classpath
  4. 12 0
      test-plugins/org.yakindu.sct.generator.c.test/.project
  5. 2 1
      test-plugins/org.yakindu.sct.generator.c.test/META-INF/MANIFEST.MF
  6. 2 1
      test-plugins/org.yakindu.sct.generator.c.test/build.properties
  7. 31 0
      test-plugins/org.yakindu.sct.generator.c.test/gtests/AlwaysOncycle/AlwaysOncycle.cc
  8. 8 0
      test-plugins/org.yakindu.sct.generator.c.test/gtests/AlwaysOncycle/AlwaysOncycle.sgen
  9. 30 0
      test-plugins/org.yakindu.sct.generator.c.test/gtests/BitExpressions/BitExpressions.cc
  10. 8 0
      test-plugins/org.yakindu.sct.generator.c.test/gtests/BitExpressions/BitExpressions.sgen
  11. 46 0
      test-plugins/org.yakindu.sct.generator.c.test/gtests/Choice/Choice.cc
  12. 8 0
      test-plugins/org.yakindu.sct.generator.c.test/gtests/Choice/Choice.sgen
  13. 40 0
      test-plugins/org.yakindu.sct.generator.c.test/gtests/IntegerExpressions/IntegerExpressions.cc
  14. 8 0
      test-plugins/org.yakindu.sct.generator.c.test/gtests/IntegerExpressions/IntegerExpressions.sgen
  15. 32 0
      test-plugins/org.yakindu.sct.generator.c.test/gtests/PriorityValues/PriorityValues.cc
  16. 8 0
      test-plugins/org.yakindu.sct.generator.c.test/gtests/PriorityValues/PriorityValues.sgen
  17. 48 0
      test-plugins/org.yakindu.sct.generator.c.test/gtests/ShallowHistory/ShallowHistory.cc
  18. 8 0
      test-plugins/org.yakindu.sct.generator.c.test/gtests/ShallowHistory/ShallowHistory.sgen
  19. 43 0
      test-plugins/org.yakindu.sct.generator.c.test/src-gen/org/yakindu/sct/generator/c/test/AlwaysOncycleTest.java
  20. 43 0
      test-plugins/org.yakindu.sct.generator.c.test/src-gen/org/yakindu/sct/generator/c/test/BitExpressionsTest.java
  21. 43 0
      test-plugins/org.yakindu.sct.generator.c.test/src-gen/org/yakindu/sct/generator/c/test/ChoiceTest.java
  22. 43 0
      test-plugins/org.yakindu.sct.generator.c.test/src-gen/org/yakindu/sct/generator/c/test/IntegerExpressionsTest.java
  23. 43 0
      test-plugins/org.yakindu.sct.generator.c.test/src-gen/org/yakindu/sct/generator/c/test/PriorityValuesTest.java
  24. 43 0
      test-plugins/org.yakindu.sct.generator.c.test/src-gen/org/yakindu/sct/generator/c/test/ShallowHistoryTest.java
  25. 26 0
      test-plugins/org.yakindu.sct.generator.c.test/src/org/yakindu/sct/generator/c/gtest/GTest.java
  26. 362 0
      test-plugins/org.yakindu.sct.generator.c.test/src/org/yakindu/sct/generator/c/gtest/GTestHelper.java
  27. 287 0
      test-plugins/org.yakindu.sct.generator.c.test/src/org/yakindu/sct/generator/c/gtest/GTestRunner.java
  28. 13 0
      test-plugins/org.yakindu.sct.generator.c.test/src/org/yakindu/sct/generator/c/test/AllGUnitTests.java

+ 16 - 0
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/GeneratorExecutor.java

@@ -28,6 +28,7 @@ import org.yakindu.sct.model.sgen.GeneratorModel;
  * 
  * 
  * @author andreas muelder - Initial contribution and API
  * @author andreas muelder - Initial contribution and API
  * @author holger willebrandt - refactoring
  * @author holger willebrandt - refactoring
+ * @author markus mühlbrandt - added executeGenerator for generator models
  */
  */
 public class GeneratorExecutor {
 public class GeneratorExecutor {
 
 
@@ -61,6 +62,21 @@ public class GeneratorExecutor {
 				.buildRule());
 				.buildRule());
 		generatorJob.schedule();
 		generatorJob.schedule();
 	}
 	}
+	
+	public void executeGenerator(GeneratorModel model) {
+
+		String generatorId = model.getGeneratorId();
+		GeneratorDescriptor description = GeneratorExtensions
+				.getGeneratorDescriptorForId(generatorId);
+		if (description == null)
+			return;
+		final ISCTGenerator generator = description.createGenerator();
+		final EList<GeneratorEntry> entries = model.getEntries();
+		
+		for (GeneratorEntry generatorEntry : entries) {
+			generator.generate(generatorEntry);
+		}
+	}
 
 
 	protected Resource loadResource(IFile file) {
 	protected Resource loadResource(IFile file) {
 		Resource resource = null;
 		Resource resource = null;

+ 2 - 1
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/impl/AbstractSGraphModelGenerator.java

@@ -14,6 +14,7 @@ import java.io.File;
 import java.io.PrintWriter;
 import java.io.PrintWriter;
 
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IProject;
+import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.console.ConsolePlugin;
 import org.eclipse.ui.console.ConsolePlugin;
 import org.eclipse.ui.console.IConsole;
 import org.eclipse.ui.console.IConsole;
 import org.eclipse.ui.console.IConsoleManager;
 import org.eclipse.ui.console.IConsoleManager;
@@ -162,7 +163,7 @@ public abstract class AbstractSGraphModelGenerator implements ISCTGenerator {
 	}
 	}
 
 
 	protected final void writeToConsole(String line) {
 	protected final void writeToConsole(String line) {
-		if (!info.isClosed()) {
+		if (!info.isClosed() && PlatformUI.isWorkbenchRunning()) {
 			info.println(line);
 			info.println(line);
 		}
 		}
 	}
 	}

+ 1 - 0
test-plugins/org.yakindu.sct.generator.c.test/.classpath

@@ -3,5 +3,6 @@
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="src-gen"/>
 	<classpathentry kind="output" path="bin"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
 </classpath>

+ 12 - 0
test-plugins/org.yakindu.sct.generator.c.test/.project

@@ -20,9 +20,21 @@
 			<arguments>
 			<arguments>
 			</arguments>
 			</arguments>
 		</buildCommand>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.yakindu.sct.builder.SCTBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	</buildSpec>
 	<natures>
 	<natures>
 		<nature>org.eclipse.pde.PluginNature</nature>
 		<nature>org.eclipse.pde.PluginNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
+		<nature>org.yakindu.sct.builder.SCTNature</nature>
 	</natures>
 	</natures>
 </projectDescription>
 </projectDescription>

+ 2 - 1
test-plugins/org.yakindu.sct.generator.c.test/META-INF/MANIFEST.MF

@@ -13,4 +13,5 @@ Require-Bundle: org.junit;bundle-version="4.8.2",
  org.yakindu.sct.generator.c;bundle-version="1.0.0",
  org.yakindu.sct.generator.c;bundle-version="1.0.0",
  org.yakindu.sct.generator.core;bundle-version="1.0.0",
  org.yakindu.sct.generator.core;bundle-version="1.0.0",
  org.yakindu.sct.generator.genmodel;bundle-version="1.0.0",
  org.yakindu.sct.generator.genmodel;bundle-version="1.0.0",
- org.yakindu.sct.model.sgen;bundle-version="1.0.0"
+ org.yakindu.sct.model.sgen;bundle-version="1.0.0",
+ org.yakindu.sct.test.models;bundle-version="1.0.0"

+ 2 - 1
test-plugins/org.yakindu.sct.generator.c.test/build.properties

@@ -2,4 +2,5 @@ source.. = src/
 output.. = bin/
 output.. = bin/
 bin.includes = META-INF/,\
 bin.includes = META-INF/,\
                .,\
                .,\
-               scripts/
+               scripts/,\
+               gtests/

+ 31 - 0
test-plugins/org.yakindu.sct.generator.c.test/gtests/AlwaysOncycle/AlwaysOncycle.cc

@@ -0,0 +1,31 @@
+/**
+* Copyright (c) 2012 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
+*/
+#include "gtest/gtest.h"
+#include "AlwaysOncycle.h"
+
+TEST(StatemachineTest, alwaysOncycleTest) {
+	AlwaysOncycle handle;
+	alwaysOncycle_init(&handle);
+	alwaysOncycle_enter(&handle);
+	EXPECT_TRUE(alwaysOncycle_isActive(&handle, AlwaysOncycle_main_region_StateA));
+	while (alwaysOncycleIface_get_value(&handle) < 5) {
+		alwaysOncycle_runCycle(&handle);
+		EXPECT_TRUE(alwaysOncycle_isActive(&handle, AlwaysOncycle_main_region_StateA));
+	}
+	alwaysOncycle_runCycle(&handle);
+	EXPECT_TRUE(alwaysOncycle_isActive(&handle, AlwaysOncycle_main_region_StateB));
+	while (alwaysOncycleIface_get_value(&handle) < 5) {
+		alwaysOncycle_runCycle(&handle);
+		EXPECT_TRUE(alwaysOncycle_isActive(&handle, AlwaysOncycle_main_region_StateB));
+	}
+	alwaysOncycle_runCycle(&handle);
+	EXPECT_TRUE(alwaysOncycle_isActive(&handle, AlwaysOncycle_main_region_StateA));
+}

+ 8 - 0
test-plugins/org.yakindu.sct.generator.c.test/gtests/AlwaysOncycle/AlwaysOncycle.sgen

@@ -0,0 +1,8 @@
+GeneratorModel for yakindu::c {
+	statechart AlwaysOncycle {
+		feature Outlet {
+			targetProject = "gtests"
+			targetFolder = "AlwaysOncycle"
+		}
+	}
+}

+ 30 - 0
test-plugins/org.yakindu.sct.generator.c.test/gtests/BitExpressions/BitExpressions.cc

@@ -0,0 +1,30 @@
+/**
+* Copyright (c) 2012 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
+*/
+#include "gtest/gtest.h"
+#include "BitExpressions.h"
+
+TEST(StatemachineTest, BitExpressions) {
+	BitExpressions handle;
+	bitExpressions_init(&handle);
+	bitExpressions_enter(&handle);
+	EXPECT_TRUE(bitExpressions_isActive(&handle, BitExpressions_main_region_StateA));
+	EXPECT_TRUE(bitExpressionsIface_get_myBit1(&handle) == 5);
+	EXPECT_TRUE(bitExpressionsIface_get_myBit2(&handle) == 7);
+	bitExpressionsIface_raise_e1(&handle);
+	bitExpressions_runCycle(&handle);
+	EXPECT_TRUE(bitExpressions_isActive(&handle, BitExpressions_main_region_StateB));
+	EXPECT_TRUE(bitExpressionsIface_get_leftBitshift(&handle) == 10);
+	EXPECT_TRUE(bitExpressionsIface_get_rightBitshift(&handle) == 2);
+	EXPECT_TRUE(bitExpressionsIface_get_complementBitshift(&handle) == - 6 );
+	EXPECT_TRUE(bitExpressionsIface_get_bitwiseAnd(&handle) == 5);
+	EXPECT_TRUE(bitExpressionsIface_get_bitwiseOr(&handle) == 7);
+	EXPECT_TRUE(bitExpressionsIface_get_bitwiseXor(&handle) == 2);
+}

+ 8 - 0
test-plugins/org.yakindu.sct.generator.c.test/gtests/BitExpressions/BitExpressions.sgen

@@ -0,0 +1,8 @@
+GeneratorModel for yakindu::c {
+	statechart BitExpressions {
+		feature Outlet {
+			targetProject = "gtests"
+			targetFolder = "BitExpressions"
+		}
+	}
+}

+ 46 - 0
test-plugins/org.yakindu.sct.generator.c.test/gtests/Choice/Choice.cc

@@ -0,0 +1,46 @@
+/**
+* Copyright (c) 2012 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
+*/
+#include "gtest/gtest.h"
+#include "Choice.h"
+
+TEST(StatemachineTest, choiceTest) {
+	Choice handle;
+	choice_init(&handle);
+	choice_enter(&handle);
+	EXPECT_TRUE(choice_isActive(&handle, Choice_main_region_A));
+	EXPECT_TRUE(choiceIface_get_value(&handle) == 4);
+	choiceIface_raise_pressKey(&handle);
+	choice_runCycle(&handle);
+	EXPECT_TRUE(choice_isActive(&handle, Choice_main_region_B));
+	EXPECT_TRUE(choiceIface_get_value(&handle) == 3);
+	choiceIface_raise_pressKey(&handle);
+	choice_runCycle(&handle);
+	EXPECT_TRUE(choice_isActive(&handle, Choice_main_region_A));
+	choiceIface_raise_pressKey(&handle);
+	choice_runCycle(&handle);
+	EXPECT_TRUE(choice_isActive(&handle, Choice_main_region_C));
+	EXPECT_TRUE(choiceIface_get_value(&handle) == 2);
+	choiceIface_raise_pressKey(&handle);
+	choice_runCycle(&handle);
+	EXPECT_TRUE(choice_isActive(&handle, Choice_main_region_B));
+	EXPECT_TRUE(choiceIface_get_value(&handle) == 1);
+	choiceIface_raise_pressKey(&handle);
+	choice_runCycle(&handle);
+	EXPECT_TRUE(choice_isActive(&handle, Choice_main_region_A));
+	EXPECT_TRUE(choiceIface_get_value(&handle) == 1);
+	choiceIface_raise_pressKey(&handle);
+	choice_runCycle(&handle);
+	EXPECT_TRUE(choice_isActive(&handle, Choice_main_region_C));
+	EXPECT_TRUE(choiceIface_get_value(&handle) == 0);
+	choiceIface_raise_pressKey(&handle);
+	choice_runCycle(&handle);
+	EXPECT_TRUE(choice_isActive(&handle, Choice_main_region_A));
+}

+ 8 - 0
test-plugins/org.yakindu.sct.generator.c.test/gtests/Choice/Choice.sgen

@@ -0,0 +1,8 @@
+GeneratorModel for yakindu::c {
+	statechart Choice {
+		feature Outlet {
+			targetProject = "gtests"
+			targetFolder = "Choice"
+		}
+	}
+}

+ 40 - 0
test-plugins/org.yakindu.sct.generator.c.test/gtests/IntegerExpressions/IntegerExpressions.cc

@@ -0,0 +1,40 @@
+/**
+* Copyright (c) 2012 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
+*/
+#include "gtest/gtest.h"
+#include "IntegerExpressions.h"
+
+TEST(StatemachineTest, integerExpressions) {
+	IntegerExpressions handle;
+	integerExpressions_init(&handle);
+	integerExpressions_enter(&handle);
+	EXPECT_TRUE(integerExpressions_isActive(&handle, IntegerExpressions_main_region_StateA));
+	EXPECT_TRUE(integerExpressionsIface_get_myInt1(&handle) == 10);
+	EXPECT_TRUE(integerExpressionsIface_get_myInt2(&handle) == 5);
+	integerExpressionsIface_raise_e1(&handle);
+	integerExpressions_runCycle(&handle);
+	EXPECT_TRUE(integerExpressionsIface_get_less(&handle) == false);
+	EXPECT_TRUE(integerExpressionsIface_get_greater(&handle) == true);
+	EXPECT_TRUE(integerExpressionsIface_get_equalOrLess(&handle) == false);
+	EXPECT_TRUE(integerExpressionsIface_get_equalOrGreater(&handle) == true);
+	EXPECT_TRUE(integerExpressionsIface_get_equal(&handle) == false);
+	EXPECT_TRUE(integerExpressionsIface_get_notEqual(&handle) == true);
+	EXPECT_TRUE(integerExpressionsIface_get_plus(&handle) == 15);
+	EXPECT_TRUE(integerExpressionsIface_get_minus(&handle) == 5);
+	EXPECT_TRUE(integerExpressionsIface_get_multiply(&handle) == 50);
+	EXPECT_TRUE(integerExpressionsIface_get_division(&handle) == 2);
+	EXPECT_TRUE(integerExpressionsIface_get_modulo(&handle) == 0);
+	EXPECT_TRUE(integerExpressionsIface_get_negat(&handle) == - 10 );
+	EXPECT_TRUE(integerExpressionsIface_get_multiAssign(&handle) == 20);
+	EXPECT_TRUE(integerExpressionsIface_get_divAssign(&handle) == 2);
+	EXPECT_TRUE(integerExpressionsIface_get_plusAssign(&handle) == 12);
+	EXPECT_TRUE(integerExpressionsIface_get_minusAssign(&handle) == - 8 );
+	EXPECT_TRUE(integerExpressionsIface_get_moduloAssign(&handle) == 0);
+}

+ 8 - 0
test-plugins/org.yakindu.sct.generator.c.test/gtests/IntegerExpressions/IntegerExpressions.sgen

@@ -0,0 +1,8 @@
+GeneratorModel for yakindu::c {
+	statechart IntegerExpressions {
+		feature Outlet {
+			targetProject = "gtests"
+			targetFolder = "IntegerExpressions"
+		}
+	}
+}

+ 32 - 0
test-plugins/org.yakindu.sct.generator.c.test/gtests/PriorityValues/PriorityValues.cc

@@ -0,0 +1,32 @@
+/**
+* Copyright (c) 2012 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
+*/
+#include "gtest/gtest.h"
+#include "PriorityValues.h"
+
+TEST(StatemachineTest, transitionPriority) {
+	PriorityValues handle;
+	priorityValues_init(&handle);
+	priorityValues_enter(&handle);
+	EXPECT_TRUE(priorityValues_isActive(&handle, PriorityValues_main_region_A));
+	priorityValuesIface_raise_event1(&handle);
+	priorityValues_runCycle(&handle);
+	EXPECT_TRUE(priorityValues_isActive(&handle, PriorityValues_main_region_C));
+}
+TEST(StatemachineTest, regionPriority) {
+	PriorityValues handle;
+	priorityValues_init(&handle);
+	priorityValues_enter(&handle);
+	EXPECT_TRUE(priorityValues_isActive(&handle, PriorityValues_someRegion_A));
+	priorityValuesIface_raise_event2(&handle);
+	priorityValues_runCycle(&handle);
+	EXPECT_TRUE(priorityValues_isActive(&handle, PriorityValues_someRegion_B));
+	EXPECT_TRUE(!priorityValues_isActive(&handle, PriorityValues_main_region_E));
+}

+ 8 - 0
test-plugins/org.yakindu.sct.generator.c.test/gtests/PriorityValues/PriorityValues.sgen

@@ -0,0 +1,8 @@
+GeneratorModel for yakindu::c {
+	statechart PriorityValues {
+		feature Outlet {
+			targetProject = "gtests"
+			targetFolder = "PriorityValues"
+		}
+	}
+}

+ 48 - 0
test-plugins/org.yakindu.sct.generator.c.test/gtests/ShallowHistory/ShallowHistory.cc

@@ -0,0 +1,48 @@
+/**
+* Copyright (c) 2012 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
+*/
+#include "gtest/gtest.h"
+#include "ShallowHistory.h"
+
+TEST(StatemachineTest, shallowHistoryTest) {
+	ShallowHistory handle;
+	shallowHistory_init(&handle);
+	shallowHistory_enter(&handle);
+	shallowHistoryIface_raise_event1(&handle);
+	shallowHistory_runCycle(&handle);
+	shallowHistoryIface_raise_event3(&handle);
+	shallowHistory_runCycle(&handle);
+	shallowHistoryIface_raise_event5(&handle);
+	shallowHistory_runCycle(&handle);
+	shallowHistoryIface_raise_event7(&handle);
+	shallowHistory_runCycle(&handle);
+	EXPECT_TRUE(!shallowHistory_isActive(&handle, ShallowHistory_mainRegion_State1));
+	EXPECT_TRUE(shallowHistory_isActive(&handle, ShallowHistory_mainRegion_State2__region0_State4__region0_State7__region0_State9));
+	shallowHistoryIface_raise_event6(&handle);
+	shallowHistory_runCycle(&handle);
+	EXPECT_TRUE(!shallowHistory_isActive(&handle, ShallowHistory_mainRegion_State2__region0_State4__region0_State7__region0_State9));
+	EXPECT_TRUE(shallowHistory_isActive(&handle, ShallowHistory_mainRegion_State2__region0_State4__region0_State6));
+	shallowHistoryIface_raise_event5(&handle);
+	shallowHistory_runCycle(&handle);
+	EXPECT_TRUE(!shallowHistory_isActive(&handle, ShallowHistory_mainRegion_State2__region0_State4__region0_State7__region0_State8));
+	EXPECT_TRUE(shallowHistory_isActive(&handle, ShallowHistory_mainRegion_State2__region0_State4__region0_State7__region0_State9));
+	shallowHistoryIface_raise_event2(&handle);
+	shallowHistory_runCycle(&handle);
+	EXPECT_TRUE(!shallowHistory_isActive(&handle, ShallowHistory_mainRegion_State2__region0_State4__region0_State7__region0_State9));
+	EXPECT_TRUE(shallowHistory_isActive(&handle, ShallowHistory_mainRegion_State1));
+	shallowHistoryIface_raise_event1(&handle);
+	shallowHistory_runCycle(&handle);
+	EXPECT_TRUE(shallowHistory_isActive(&handle, ShallowHistory_mainRegion_State2__region0_State4__region0_State6));
+	EXPECT_TRUE(!shallowHistory_isActive(&handle, ShallowHistory_mainRegion_State1));
+	shallowHistoryIface_raise_event5(&handle);
+	shallowHistory_runCycle(&handle);
+	EXPECT_TRUE(!shallowHistory_isActive(&handle, ShallowHistory_mainRegion_State2__region0_State4__region0_State6));
+	EXPECT_TRUE(shallowHistory_isActive(&handle, ShallowHistory_mainRegion_State2__region0_State4__region0_State7__region0_State9));
+}

+ 8 - 0
test-plugins/org.yakindu.sct.generator.c.test/gtests/ShallowHistory/ShallowHistory.sgen

@@ -0,0 +1,8 @@
+GeneratorModel for yakindu::c {
+	statechart ShallowHistory {
+		feature Outlet {
+			targetProject = "gtests"
+			targetFolder = "ShallowHistory"
+		}
+	}
+}

+ 43 - 0
test-plugins/org.yakindu.sct.generator.c.test/src-gen/org/yakindu/sct/generator/c/test/AlwaysOncycleTest.java

@@ -0,0 +1,43 @@
+/**
+* Copyright (c) 2012 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.generator.c.test;
+
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.yakindu.sct.generator.c.gtest.GTest;
+import org.yakindu.sct.generator.c.gtest.GTestRunner;
+import org.yakindu.sct.generator.c.gtest.GTestHelper;
+
+@GTest(sourceFile = "gtests/AlwaysOncycle/AlwaysOncycle.cc", program = "gtests/AlwaysOncycle/AlwaysOncycle", model = "testmodels/AlwaysOncycle.sct" )
+@RunWith(GTestRunner.class)
+public class AlwaysOncycleTest {
+
+	protected final GTestHelper helper = new GTestHelper(this) {
+
+		@Override
+		protected void getSourceFiles(Collection<String> files) {
+			super.getSourceFiles(files);
+		files.add(getFileName(getTestProgram()) + ".c");
+		}
+	};
+
+	@Before
+	public void setUp() {
+		generateAndCompile();
+	}
+
+	protected void generateAndCompile() {
+		helper.generate();
+		helper.compile();
+	}
+}

+ 43 - 0
test-plugins/org.yakindu.sct.generator.c.test/src-gen/org/yakindu/sct/generator/c/test/BitExpressionsTest.java

@@ -0,0 +1,43 @@
+/**
+* Copyright (c) 2012 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.generator.c.test;
+
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.yakindu.sct.generator.c.gtest.GTest;
+import org.yakindu.sct.generator.c.gtest.GTestRunner;
+import org.yakindu.sct.generator.c.gtest.GTestHelper;
+
+@GTest(sourceFile = "gtests/BitExpressions/BitExpressions.cc", program = "gtests/BitExpressions/BitExpressions", model = "testmodels/BitExpressions.sct" )
+@RunWith(GTestRunner.class)
+public class BitExpressionsTest {
+
+	protected final GTestHelper helper = new GTestHelper(this) {
+
+		@Override
+		protected void getSourceFiles(Collection<String> files) {
+			super.getSourceFiles(files);
+		files.add(getFileName(getTestProgram()) + ".c");
+		}
+	};
+
+	@Before
+	public void setUp() {
+		generateAndCompile();
+	}
+
+	protected void generateAndCompile() {
+		helper.generate();
+		helper.compile();
+	}
+}

+ 43 - 0
test-plugins/org.yakindu.sct.generator.c.test/src-gen/org/yakindu/sct/generator/c/test/ChoiceTest.java

@@ -0,0 +1,43 @@
+/**
+* Copyright (c) 2012 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.generator.c.test;
+
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.yakindu.sct.generator.c.gtest.GTest;
+import org.yakindu.sct.generator.c.gtest.GTestRunner;
+import org.yakindu.sct.generator.c.gtest.GTestHelper;
+
+@GTest(sourceFile = "gtests/Choice/Choice.cc", program = "gtests/Choice/Choice", model = "testmodels/Choice.sct" )
+@RunWith(GTestRunner.class)
+public class ChoiceTest {
+
+	protected final GTestHelper helper = new GTestHelper(this) {
+
+		@Override
+		protected void getSourceFiles(Collection<String> files) {
+			super.getSourceFiles(files);
+		files.add(getFileName(getTestProgram()) + ".c");
+		}
+	};
+
+	@Before
+	public void setUp() {
+		generateAndCompile();
+	}
+
+	protected void generateAndCompile() {
+		helper.generate();
+		helper.compile();
+	}
+}

+ 43 - 0
test-plugins/org.yakindu.sct.generator.c.test/src-gen/org/yakindu/sct/generator/c/test/IntegerExpressionsTest.java

@@ -0,0 +1,43 @@
+/**
+* Copyright (c) 2012 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.generator.c.test;
+
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.yakindu.sct.generator.c.gtest.GTest;
+import org.yakindu.sct.generator.c.gtest.GTestRunner;
+import org.yakindu.sct.generator.c.gtest.GTestHelper;
+
+@GTest(sourceFile = "gtests/IntegerExpressions/IntegerExpressions.cc", program = "gtests/IntegerExpressions/IntegerExpressions", model = "testmodels/IntegerExpressions.sct" )
+@RunWith(GTestRunner.class)
+public class IntegerExpressionsTest {
+
+	protected final GTestHelper helper = new GTestHelper(this) {
+
+		@Override
+		protected void getSourceFiles(Collection<String> files) {
+			super.getSourceFiles(files);
+		files.add(getFileName(getTestProgram()) + ".c");
+		}
+	};
+
+	@Before
+	public void setUp() {
+		generateAndCompile();
+	}
+
+	protected void generateAndCompile() {
+		helper.generate();
+		helper.compile();
+	}
+}

+ 43 - 0
test-plugins/org.yakindu.sct.generator.c.test/src-gen/org/yakindu/sct/generator/c/test/PriorityValuesTest.java

@@ -0,0 +1,43 @@
+/**
+* Copyright (c) 2012 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.generator.c.test;
+
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.yakindu.sct.generator.c.gtest.GTest;
+import org.yakindu.sct.generator.c.gtest.GTestRunner;
+import org.yakindu.sct.generator.c.gtest.GTestHelper;
+
+@GTest(sourceFile = "gtests/PriorityValues/PriorityValues.cc", program = "gtests/PriorityValues/PriorityValues", model = "testmodels/PriorityValues.sct" )
+@RunWith(GTestRunner.class)
+public class PriorityValuesTest {
+
+	protected final GTestHelper helper = new GTestHelper(this) {
+
+		@Override
+		protected void getSourceFiles(Collection<String> files) {
+			super.getSourceFiles(files);
+		files.add(getFileName(getTestProgram()) + ".c");
+		}
+	};
+
+	@Before
+	public void setUp() {
+		generateAndCompile();
+	}
+
+	protected void generateAndCompile() {
+		helper.generate();
+		helper.compile();
+	}
+}

+ 43 - 0
test-plugins/org.yakindu.sct.generator.c.test/src-gen/org/yakindu/sct/generator/c/test/ShallowHistoryTest.java

@@ -0,0 +1,43 @@
+/**
+* Copyright (c) 2012 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.generator.c.test;
+
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.yakindu.sct.generator.c.gtest.GTest;
+import org.yakindu.sct.generator.c.gtest.GTestRunner;
+import org.yakindu.sct.generator.c.gtest.GTestHelper;
+
+@GTest(sourceFile = "gtests/ShallowHistory/ShallowHistory.cc", program = "gtests/ShallowHistory/ShallowHistory", model = "testmodels/ShallowHistory.sct" )
+@RunWith(GTestRunner.class)
+public class ShallowHistoryTest {
+
+	protected final GTestHelper helper = new GTestHelper(this) {
+
+		@Override
+		protected void getSourceFiles(Collection<String> files) {
+			super.getSourceFiles(files);
+		files.add(getFileName(getTestProgram()) + ".c");
+		}
+	};
+
+	@Before
+	public void setUp() {
+		generateAndCompile();
+	}
+
+	protected void generateAndCompile() {
+		helper.generate();
+		helper.compile();
+	}
+}

+ 26 - 0
test-plugins/org.yakindu.sct.generator.c.test/src/org/yakindu/sct/generator/c/gtest/GTest.java

@@ -0,0 +1,26 @@
+/****************************************************************************
+ * Copyright (c) 2008, 2012 Andreas Unger 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:
+ *    Andreas Unger - initial API and implementation 
+ ****************************************************************************/
+
+package org.yakindu.sct.generator.c.gtest;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface GTest {
+	
+	String sourceFile();
+	String program();
+	String model();
+}

+ 362 - 0
test-plugins/org.yakindu.sct.generator.c.test/src/org/yakindu/sct/generator/c/gtest/GTestHelper.java

@@ -0,0 +1,362 @@
+/****************************************************************************
+ * Copyright (c) 2008, 2012 Andreas Unger 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:
+ *    Andreas Unger - initial API and implementation 
+ ****************************************************************************/
+
+package org.yakindu.sct.generator.c.gtest;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+import org.yakindu.sct.generator.core.GeneratorExecutor;
+import org.yakindu.sct.model.sgen.GeneratorModel;
+import org.yakindu.sct.model.sgraph.Statechart;
+
+import util.TestModels;
+
+/**
+ * @author Andreas Unger - Initial contribution and API
+ * @author Markus Mühlbrandt
+ * 
+ */
+public class GTestHelper {
+
+	private final Object owner;
+
+	/**
+	 * 
+	 */
+	public GTestHelper(Object owner) {
+		this.owner = owner;
+	}
+
+	public void compile() {
+		try {
+			copyFilesFromBundleToFolder();
+			IResource resource = ResourcesPlugin.getWorkspace().getRoot()
+					.findMember(getTargetPath());
+			File directory = resource.getLocation().toFile();
+			List<String> command = createCommand();
+
+			ProcessBuilder processBuilder = new ProcessBuilder(command)
+					.directory(directory);
+			Process process = processBuilder.redirectErrorStream(true).start();
+			String message = readProcessInputStream(process);
+			process.waitFor();
+
+			if (process.exitValue() != 0) {
+				throw new RuntimeException("Compilation failed (exit status "
+						+ process.exitValue() + "):\n" + message);
+			}
+		} catch (Error e) {
+			throw e;
+		} catch (RuntimeException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		} finally {
+			try {
+				ResourcesPlugin
+						.getWorkspace()
+						.getRoot()
+						.refreshLocal(IResource.DEPTH_INFINITE,
+								new NullProgressMonitor());
+			} catch (CoreException e) {
+				throw new RuntimeException(e);
+			}
+		}
+	}
+
+	public void generate() {
+
+		IPath targetPath = getTargetPath();
+
+		// copy model to junit workspace
+		copyFileFromBundleToFolder(getModelBundle(), getModelPath(), targetPath);
+
+		String sgenFileName = getTestProgram() + ".sgen";
+		copyFileFromBundleToFolder(getTestBundle(), sgenFileName, targetPath);
+
+		IPath path = new Path(sgenFileName);
+		IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+		Resource sgenResource = loadResource(file);
+		GeneratorModel model = (GeneratorModel) sgenResource.getContents().get(
+				0);
+		model.getEntries().get(0).setElementRef(getStatechart());
+		new GeneratorExecutor().executeGenerator(model);
+	}
+
+	protected Statechart getStatechart() {
+		IPath path = new Path(getTargetPath().toString() + "/"
+				+ getModelPath().lastSegment());
+		IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+		Resource resource = loadResource(file);
+		return (Statechart) resource.getContents().get(0);
+	}
+
+	protected Resource loadResource(IFile file) {
+		Resource resource = null;
+		URI uri = URI.createPlatformResourceURI(file.getFullPath().toString(),
+				true);
+		resource = new ResourceSetImpl().getResource(uri, true);
+		return resource;
+	}
+
+	protected Bundle getModelBundle() {
+		return FrameworkUtil.getBundle(TestModels.class);
+	}
+
+	private void copyFilesFromBundleToFolder() {
+		IPath targetPath = getTargetPath();
+		List<String> testDataFiles = new ArrayList<String>();
+		getTestDataFiles(testDataFiles);
+		for (String file : testDataFiles) {
+			copyFileFromBundleToFolder(getTestBundle(), file, targetPath);
+		}
+	}
+
+	private String readProcessInputStream(Process process) throws IOException {
+		Reader reader = new InputStreamReader(process.getInputStream());
+		char[] buffer = new char[4096];
+		int count;
+		StringBuilder message = new StringBuilder();
+		while ((count = reader.read(buffer)) != -1) {
+			message.append(buffer, 0, count);
+		}
+		return message.toString();
+	}
+
+	protected List<String> createCommand() {
+		//String gTestDirectory = getGTestDirectory();
+
+		List<String> includes = new ArrayList<String>();
+		getIncludes(includes);
+
+		List<String> sourceFiles = new ArrayList<String>();
+		getSourceFiles(sourceFiles);
+
+		List<String> command = new ArrayList<String>();
+		command.add(getCompilerCommand());
+		command.add("-o");
+		command.add(getFileName(getTestProgram()));
+		//command.add("-I" + gTestDirectory + "/include");
+		for (String include : includes) {
+			command.add("-I" + include);
+		}
+		//command.add("-L" + gTestDirectory);
+		for (String sourceFile : sourceFiles) {
+			command.add(sourceFile);
+		}
+		command.add("-lgtest");
+		command.add("-lgtest_main");
+		command.add("-lstdc++");
+		command.add("-pthread");
+		return command;
+	}
+
+	/**
+	 * @return
+	 */
+	protected String getCompilerCommand() {
+		return "gcc";
+	}
+
+//	/**
+//	 * @return
+//	 */
+//	private String getGTestDirectory() {
+//		String gTestDirectory = System.getenv("GTEST_DIR");
+//		if (gTestDirectory == null) {
+//			throw new RuntimeException("GTEST_DIR environment variable not set");
+//		}
+//		return gTestDirectory;
+//	}
+
+	protected String getFileName(String path) {
+		return new Path(path).lastSegment();
+	}
+
+	protected IPath getTargetPath() {
+		return new Path(getTestProgram()).removeLastSegments(1);
+	}
+
+	protected IPath getModelPath() {
+		return new Path(getModelAnnotation());
+	}
+
+	protected void getIncludes(Collection<String> includes) {
+	}
+
+	protected void getSourceFiles(Collection<String> files) {
+		files.add(getFileName(getTestSourceFile()));
+	}
+
+	protected String getTestSourceFile() {
+		return owner.getClass().getAnnotation(GTest.class).sourceFile();
+	}
+
+	protected void getTestDataFiles(Collection<String> files) {
+		files.add(getTestSourceFile());
+	}
+
+	protected String getTestProgram() {
+		return owner.getClass().getAnnotation(GTest.class).program();
+	}
+
+	protected String getModelAnnotation() {
+		return owner.getClass().getAnnotation(GTest.class).model();
+	}
+
+	protected void copyFileFromBundleToFolder(Bundle bundle, String sourcePath,
+			String targetPath) {
+		copyFileFromBundleToFolder(bundle, new Path(sourcePath), new Path(
+				targetPath));
+	}
+
+	protected void copyFileFromBundleToFolder(Bundle bundle, String sourcePath,
+			IPath targetPath) {
+		copyFileFromBundleToFolder(bundle, new Path(sourcePath), targetPath);
+	}
+
+	protected void copyFileFromBundleToFolder(Bundle bundle, IPath sourcePath,
+			IPath targetPath) {
+		String fileName = sourcePath.lastSegment();
+		copyFileFromBundle(bundle, sourcePath, targetPath.append(fileName));
+	}
+
+	protected void copyFileFromBundle(Bundle bundle, String sourcePath,
+			String targetPath) {
+		copyFileFromBundle(bundle, sourcePath, new Path(targetPath));
+	}
+
+	protected void copyFileFromBundle(Bundle bundle, String sourcePath,
+			IPath targetPath) {
+		copyFileFromBundle(bundle, new Path(sourcePath), targetPath);
+	}
+
+	protected void copyFileFromBundle(Bundle bundle, IPath sourcePath,
+			IPath targetPath) {
+		try {
+			InputStream is = FileLocator.openStream(bundle, sourcePath, false);
+			createFile(targetPath, is);
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	protected Bundle getTestBundle() {
+		return FrameworkUtil.getBundle(owner.getClass());
+	}
+
+	protected void copyFileFromBundle(String sourcePath, IFile targetFile) {
+		copyFileFromBundle(new Path(sourcePath), targetFile);
+	}
+
+	protected void copyFileFromBundle(IPath sourcePath, IFile targetFile) {
+		try {
+			InputStream is = FileLocator.openStream(getTestBundle(),
+					sourcePath, false);
+			createFile(targetFile, is);
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	protected void createFile(String path, InputStream source) {
+		createFile(new Path(path), source);
+	}
+
+	protected void createFile(IPath path, InputStream source) {
+		IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+		createFile(file, source);
+	}
+
+	protected void createFile(IFile file, InputStream source) {
+		ensureContainerExists(file.getParent());
+		try {
+			if (file.exists()) {
+				file.setContents(source, true, false, new NullProgressMonitor());
+			} else {
+				file.create(source, true, new NullProgressMonitor());
+			}
+		} catch (CoreException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	protected IFolder getFolder(String path) {
+		return ensureContainerExists(ResourcesPlugin.getWorkspace().getRoot()
+				.getFolder(new Path(path)));
+	}
+
+	protected IFolder getFolder(IPath path) {
+		return ensureContainerExists(ResourcesPlugin.getWorkspace().getRoot()
+				.getFolder(path));
+	}
+
+	protected <T extends IContainer> T ensureContainerExists(T container) {
+		IProgressMonitor monitor = new NullProgressMonitor();
+		IProject project = container.getProject();
+		if (project.exists()) {
+			if (!project.isOpen()) {
+				throw new RuntimeException("Project " + project.getName()
+						+ " closed");
+			}
+		} else {
+			try {
+				project.create(monitor);
+				project.open(monitor);
+			} catch (CoreException e) {
+				throw new RuntimeException(e);
+			}
+		}
+		if (container instanceof IFolder) {
+			doEnsureFolderExists((IFolder) container, monitor);
+		}
+		return container;
+	}
+
+	private void doEnsureFolderExists(IFolder folder, IProgressMonitor monitor) {
+		if (!folder.exists()) {
+			if (!folder.getParent().exists()
+					&& folder.getParent() instanceof IFolder) {
+				doEnsureFolderExists((IFolder) folder.getParent(), monitor);
+			}
+			try {
+				folder.create(true, true, monitor);
+			} catch (CoreException e) {
+				throw new RuntimeException(e);
+			}
+		}
+	}
+
+}

+ 287 - 0
test-plugins/org.yakindu.sct.generator.c.test/src/org/yakindu/sct/generator/c/gtest/GTestRunner.java

@@ -0,0 +1,287 @@
+/****************************************************************************
+ * Copyright (c) 2008, 2012 Andreas Unger 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:
+ *    Andreas Unger - initial API and implementation 
+ ****************************************************************************/
+
+package org.yakindu.sct.generator.c.gtest;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import junit.framework.AssertionFailedError;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.Path;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.model.InitializationError;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+
+/**
+ * @author Andreas Unger
+ * 
+ */
+public class GTestRunner extends Runner {
+
+	private static final Pattern TEST_PATTERN = Pattern.compile("TEST(?:_F)?\\s*\\(\\s*(\\w+)\\s*,\\s*(\\w+)\\s*\\)");
+	private static final Pattern SL_COMMENT_PATTERN = Pattern.compile("//.*(?:\\r?\\n|\\z)");
+	private static final Pattern ML_COMMENT_PATTERN = Pattern.compile("/\\*.*\\*/", Pattern.DOTALL);
+	private static final Pattern TEST_OUTPUT_PATTERN = Pattern.compile("\\[\\s*(\\w+)\\s*\\] (\\w+)\\.(\\w+)");
+
+	private Class<?> testClass;
+
+	private Map<String, List<String>> testCases = new LinkedHashMap<String, List<String>>();
+
+	/**
+	 * 
+	 */
+	public GTestRunner(Class<?> testClass) throws InitializationError {
+		this.testClass = testClass;
+
+		GTest annotation = testClass.getAnnotation(GTest.class);
+		if (annotation == null) {
+			throw new InitializationError("Test class must specify " + GTest.class.getCanonicalName() + " annotation");
+		}
+
+		String sourceFile = annotation.sourceFile();
+		try {
+			CharSequence charSequence = readSourceFile(sourceFile);
+			String s = ML_COMMENT_PATTERN.matcher(SL_COMMENT_PATTERN.matcher(charSequence).replaceAll("")).replaceAll("");
+			Matcher matcher = TEST_PATTERN.matcher(s);
+			while (matcher.find()) {
+				String testCaseName = matcher.group(1);
+				String testName = matcher.group(2);
+				List<String> testCase = testCases.get(testCaseName);
+				if (testCase == null) {
+					testCase = new ArrayList<String>();
+					testCases.put(testCaseName, testCase);
+				}
+				testCase.add(testName);
+			}
+		} catch (IOException e) {
+			throw new InitializationError(e);
+		}
+
+		if (testCases.isEmpty()) {
+			throw new InitializationError("No tests specified");
+		}
+	}
+
+	private CharSequence readSourceFile(String sourceFile) throws IOException {
+		Bundle bundle = FrameworkUtil.getBundle(testClass);
+		InputStream is = FileLocator.openStream(bundle, new Path(sourceFile),
+				false);
+		Reader reader = new InputStreamReader(is);
+		char[] buffer = new char[4096];
+		StringBuilder sb = new StringBuilder(buffer.length);
+		int count;
+		while ((count = reader.read(buffer)) != -1) {
+			sb.append(buffer, 0, count);
+		}
+		return sb;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.junit.runner.Runner#getDescription()
+	 */
+	@Override
+	public Description getDescription() {
+		Description description = Description.createSuiteDescription(testClass);
+		for (Entry<String, List<String>> entry : testCases.entrySet()) {
+			for (String test : entry.getValue()) {
+				String testCase = entry.getKey();
+				Description childDescription = createDescription(testCase, test);
+				description.addChild(childDescription);
+			}
+		}
+		return description;
+	}
+
+	private Description createDescription(String testCase, String test) {
+		String name;
+		if (testCases.size() == 1) {
+			name = test;
+		} else {
+			name = testCase + "." + test;
+		}
+		return Description.createTestDescription(testClass, name);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.junit.runner.Runner#run(org.junit.runner.notification.RunNotifier)
+	 */
+	@Override
+	public void run(RunNotifier notifier) {
+		try {
+			Object test = testClass.newInstance();
+			Method[] methods = testClass.getMethods();
+
+			for (Method method : methods) {
+				if (method.isAnnotationPresent(Before.class)) {
+					method.invoke(test);
+				}
+			}
+
+			runGTests(notifier);
+
+			for (Method method : methods) {
+				if (method.isAnnotationPresent(After.class)) {
+					method.invoke(test);
+				}
+			}
+		} catch (InvocationTargetException e) {
+			Throwable targetException = ((InvocationTargetException) e).getTargetException();
+			notifier.fireTestFailure(new Failure(getDescription(), targetException));
+		} catch (Throwable throwable) {
+			notifier.fireTestFailure(new Failure(getDescription(), throwable));
+		}
+	}
+
+	private void runGTests(RunNotifier notifier) throws IOException, InterruptedException {
+		String program = testClass.getAnnotation(GTest.class).program();
+		IResource programFile = ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(program));
+		IContainer programContainer = programFile.getParent();
+		if (!programContainer.isAccessible()) {
+			throw new RuntimeException("Test program container " + programContainer.getLocation().toOSString() + " inaccessible");
+		}
+		
+		File directory = programContainer.getLocation().toFile();
+		Process process = new ProcessBuilder(programFile.getLocation().toOSString()).redirectErrorStream(true).directory(directory).start();
+		BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+
+		boolean started = false;
+		boolean running = false;
+		StringBuilder message = new StringBuilder();
+		String line;
+		while ((line = reader.readLine()) != null) {
+			if (line.startsWith("[====")) {
+				if (started) {
+					started = false;
+					// Eat remaining input
+					char[] buffer = new char[4096];
+					while (reader.read(buffer) != -1);
+					break;
+				}
+				started = true;
+			} else {
+				TestOutput testOutput = parseTestOutput(line);
+				if (testOutput != null) {
+					Description description = testOutput.toDescription();
+					switch (testOutput.getStatus()) {
+					case TestOutput.RUN:
+						running = true;
+						message.setLength(0);
+						notifier.fireTestStarted(description);
+						break;
+					case TestOutput.OK:
+						running = false;
+						notifier.fireTestFinished(description);
+						break;
+					default:
+						running = false;
+						notifier.fireTestFailure(new Failure(description, new AssertionFailedError(message.toString())));
+						notifier.fireTestFinished(description);
+						break;
+					}
+				} else if (running) {
+					message.append(line);
+					message.append("\n");
+				}
+			}
+		}
+
+		process.waitFor();
+		
+		if (started) {
+			throw new RuntimeException("Test quit unexpectedly (exit status " + process.exitValue() + "):\n" + message);
+		}
+	}
+
+	private TestOutput parseTestOutput(String s) {
+		Matcher matcher = TEST_OUTPUT_PATTERN.matcher(s);
+		if (matcher.find()) {
+			String statusString = matcher.group(1);
+			int status;
+			if ("RUN".equals(statusString)) {
+				status = TestOutput.RUN;
+			} else if ("OK".equals(statusString)) {
+				status = TestOutput.OK;
+			} else {
+				status = TestOutput.FAILED;
+			}
+			String testCaseName = matcher.group(2);
+			String testName = matcher.group(3);
+			return new TestOutput(status, testCaseName, testName);
+		}
+		return null;
+	}
+
+	private class TestOutput {
+
+		public static final int RUN = 0;
+		public static final int OK = 1;
+		public static final int FAILED = 2;
+
+		private int status;
+
+		private String testCaseName;
+		private String testName;
+
+		public TestOutput(int status, String testCaseName, String testName) {
+			this.status = status;
+			this.testCaseName = testCaseName;
+			this.testName = testName;
+		}
+
+		/**
+		 * @return the status
+		 */
+		public int getStatus() {
+			return status;
+		}
+
+		public Description toDescription() {
+			String name;
+			if (testCases.size() == 1) {
+				name = testName;
+			} else {
+				name = testCaseName + "." + testName;
+			}
+			return Description.createTestDescription(testClass, name);
+		}
+
+	}
+
+}

+ 13 - 0
test-plugins/org.yakindu.sct.generator.c.test/src/org/yakindu/sct/generator/c/test/AllGUnitTests.java

@@ -0,0 +1,13 @@
+package org.yakindu.sct.generator.c.test;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+//TODO: The testsuite should be generated too
+@RunWith(Suite.class)
+@SuiteClasses({ AlwaysOncycleTest.class, BitExpressionsTest.class,
+		ChoiceTest.class, IntegerExpressionsTest.class,
+		PriorityValuesTest.class, ShallowHistoryTest.class })
+public class AllGUnitTests {
+
+}