/*
 * This file has been developed at the University of Munich, Chair for Programming & Software Engineering.
 * 
 * This file is licensed under the Eclipse Public License (EPL) 1.0
 * 
 */
package eu.uml4soa.utbm.u2m.test;

import org.junit.Test;

import eu.mdd4soa.smm.behaviour.CompensationHandler;
import eu.mdd4soa.smm.behaviour.ServiceActivity;
import eu.uml4soa.utbm.u2m.model.CAutomaton;
import eu.uml4soa.utbm.u2m.semantics.OrchestrationSemanticsFunction;

/**
 * This class tests the basic interaction features like send, receive,
 * send&receive in the conversion.
 * 
 * @author Philip Mayer, mayer@pst.ifi.lmu.de
 * 
 */
public class TestLoop extends AbstractSemanticTests {

	/**
	 * Tests a loop.
	 * 
	 * @throws Exception
	 */
	@Test
	public void testLoop() throws Exception {

		ServiceActivity sa= createActivity("Test Decision");
		sa.getChildren().add(createLoop(createSend("send1"), createSend("send2")));

		CAutomaton c= OrchestrationSemanticsFunction.transform(sa);
		// store("resources/testLoop", c);
		compareMios(c, "testLoop");
	}

	/**
	 * Tests two loops. There MUST be an intermediate step there to avoid
	 * running BOTH loops again and again!!
	 * 
	 * 
	 * @throws Exception
	 */
	@Test
	public void testLoopTwoLoops() throws Exception {

		ServiceActivity sa= createActivity("Test Two Loops");
		sa.getChildren().add(createLoop(createSend("send1")));
		sa.getChildren().add(createLoop(createSend("send2")));

		CAutomaton c= OrchestrationSemanticsFunction.transform(sa);
		// store("resources/testLoopTwoLoops", c);
		compareMios(c, "testLoopTwoLoops");
	}



	/**
	 * Tests a loop and something after the loop to see it is okay.
	 * 
	 * @throws Exception
	 */
	@Test
	public void testLoopAndAfter() throws Exception {

		ServiceActivity sa= createActivity("Test Loop");
		sa.getChildren().add(createLoop(createSend("send1"), createSend("send2")));
		sa.getChildren().add(createSend("sendAfterLoop"));

		CAutomaton c= OrchestrationSemanticsFunction.transform(sa);
		// store("resources/testLoopAndAfter", c);
		compareMios(c, "testLoopAndAfter");
	}

	/**
	 * Tests a bug in the translation: If the beginning of a loop and another
	 * node are merged, one can go back in the loop and then elsewhere. This is
	 * not allowed.
	 * 
	 * Also: At the end of the loop, we may not "jump into the loop" if we have
	 * not performed it before.
	 * 
	 * @throws Exception
	 */
	@Test
	public void testLoopAndDecision() throws Exception {

		ServiceActivity sa= createActivity("Test Loop and Decision");
		sa.getChildren().add(createDecision(createSend("sendOut"), createLoop(createSend("send1"), createSend("send2"))));

		CAutomaton c= OrchestrationSemanticsFunction.transform(sa);
		// store("resources/testLoopAndDecision", c);
		compareMios(c, "testLoopAndDecision");
	}

	/**
	 * This demonstrates why we need a pre- AND postfix in a loop.
	 * 
	 * @throws Exception
	 */
	@Test
	public void testLoop2InDec() throws Exception {

		ServiceActivity sa= createActivity("Test Loop and Decision");
		sa.getChildren().add(createDecision(createLoop(createSend("send1")), createLoop(createSend("send2"))));

		CAutomaton c= OrchestrationSemanticsFunction.transform(sa);
		// store("resources/testLoop2InDec", c);
		compareMios(c, "testLoop2InDec");
	}

	/**
	 * This demonstrates why we need a pre- AND postfix in a loop.
	 * 
	 * @throws Exception
	 */
	@Test
	public void testLoop1InPar() throws Exception {

		ServiceActivity sa= createActivity("Test Loop and Decision");
		sa.getChildren().add(createReceive("before"));
		sa.getChildren().add(createParallel(createLoop(createSend("sendInLoop")), createSend("sendNotInLoop")));
		sa.getChildren().add(createReceive("after"));

		CAutomaton c= OrchestrationSemanticsFunction.transform(sa);
		// store("resources/testLoop1InPar", c);
		compareMios(c, "testLoop1InPar");
	}

	/**
	 * This demonstrates why we need a pre- AND postfix in a loop.
	 * 
	 * @throws Exception
	 */
	@Test
	public void testLoop2InPar() throws Exception {

		ServiceActivity sa= createActivity("Test Loop and Decision");
		sa.getChildren().add(createReceive("before"));
		sa.getChildren().add(createParallel(createLoop(createSend("send1")), createLoop(createSend("send2"))));
		sa.getChildren().add(createReceive("after"));

		CAutomaton c= OrchestrationSemanticsFunction.transform(sa);
		// store("resources/testLoop2InPar", c);
		compareMios(c, "testLoop2InPar");
	}

	/**
	 * This tests a comp.handler install in a loop.
	 * 
	 * @throws Exception
	 */
	@Test
	public void testLoopCompInLoop() throws Exception {

		ServiceActivity inner= createActivity("Inner");
		inner.getChildren().add(createSend("innerSend"));

		CompensationHandler h= createCompensationHandler("CHandler", createSend("compSend"));
		inner.getHandlers().add(h);

		ServiceActivity sa= createActivity("Outer");
		sa.getChildren().add(createLoop(inner));

		CAutomaton c= OrchestrationSemanticsFunction.transform(sa);
		// store("resources/testLoopCompInLoop", c);
		compareMios(c, "testLoopCompInLoop");
	}

	/**
	 * This tests two compensation installations in a loop.
	 * 
	 * @throws Exception
	 */
	@Test
	public void testLoop2CompInLoop() throws Exception {

		ServiceActivity sa= createActivity("TestHandler");

		ServiceActivity inner1= createActivity("Inner1");
		inner1.getChildren().add(createSend("sndInner1"));
		ServiceActivity inner2= createActivity("Inner2");
		inner2.getChildren().add(createSend("sndInner2"));

		inner1.getHandlers().add(createCompensationHandler("CompHandler1", createSend("sendComp1")));
		inner2.getHandlers().add(createCompensationHandler("CompHandler2", createSend("sendComp2")));

		sa.getChildren().add(createLoop(createDecision(inner1, inner2)));

		CAutomaton c= OrchestrationSemanticsFunction.transform(sa);
		// store("resources/testLoop2CompInLoop", c);
		compareMios(c, "testLoop2CompInLoop");
	}


}
