/* * Catroid: An on-device visual programming system for Android devices * Copyright (C) 2010-2016 The Catrobat Team * (<http://developer.catrobat.org/credits>) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * An additional term exception under section 7 of the GNU Affero * General Public License, version 3, is available at * http://developer.catrobat.org/license_additional_term * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.catrobat.catroid.test.content.actions; import android.test.InstrumentationTestCase; import com.badlogic.gdx.scenes.scene2d.Action; import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction; import org.catrobat.catroid.content.Script; import org.catrobat.catroid.content.SingleSprite; import org.catrobat.catroid.content.Sprite; import org.catrobat.catroid.content.StartScript; import org.catrobat.catroid.content.actions.RepeatAction; import org.catrobat.catroid.content.bricks.ChangeYByNBrick; import org.catrobat.catroid.content.bricks.LoopEndBrick; import org.catrobat.catroid.content.bricks.RepeatBrick; import org.catrobat.catroid.formulaeditor.Formula; import org.catrobat.catroid.formulaeditor.FormulaElement; import org.catrobat.catroid.formulaeditor.FormulaElement.ElementType; import org.catrobat.catroid.formulaeditor.Sensors; import org.catrobat.catroid.test.utils.Reflection; import java.util.HashMap; import java.util.List; public class RepeatActionTest extends InstrumentationTestCase { private static final int REPEAT_TIMES = 4; private static final String NOT_NUMERICAL_STRING = "NOT_NUMERICAL_STRING"; private Sprite testSprite; private Script testScript; private int delta = 5; @Override protected void setUp() throws Exception { testSprite = new SingleSprite("sprite"); testScript = new StartScript(); } public void testLoopDelay() throws InterruptedException { final int deltaY = -10; final float delta = 0.005f; final float delayByContract = 0.020f; RepeatBrick repeatBrick = new RepeatBrick(REPEAT_TIMES); LoopEndBrick loopEndBrick = new LoopEndBrick(repeatBrick); repeatBrick.setLoopEndBrick(loopEndBrick); testScript.addBrick(repeatBrick); testScript.addBrick(new ChangeYByNBrick(deltaY)); testScript.addBrick(loopEndBrick); testScript.addBrick(new ChangeYByNBrick(150)); testSprite.addScript(testScript); testSprite.createStartScriptActionSequenceAndPutToMap(new HashMap<String, List<String>>()); // http://code.google.com/p/catroid/issues/detail?id=28 for (int index = 0; index < REPEAT_TIMES; index++) { for (double time = 0f; time < delayByContract; time += delta) { testSprite.look.act(delta); } } assertEquals("Loop delay did was not 20ms!", deltaY * REPEAT_TIMES, (int) testSprite.look.getYInUserInterfaceDimensionUnit()); } public void testRepeatBrick() throws InterruptedException { RepeatBrick repeatBrick = new RepeatBrick(REPEAT_TIMES); LoopEndBrick loopEndBrick = new LoopEndBrick(repeatBrick); repeatBrick.setLoopEndBrick(loopEndBrick); final int deltaY = -10; testScript.addBrick(repeatBrick); testScript.addBrick(new ChangeYByNBrick(deltaY)); testScript.addBrick(loopEndBrick); testSprite.addScript(testScript); testSprite.createStartScriptActionSequenceAndPutToMap(new HashMap<String, List<String>>()); while (!testSprite.look.getAllActionsAreFinished()) { testSprite.look.act(1.0f); } assertEquals("Executed the wrong number of times!", REPEAT_TIMES * deltaY, (int) testSprite.look.getYInUserInterfaceDimensionUnit()); } public void testRepeatCount() { Sprite testSprite = new SingleSprite("sprite"); Script testScript = new StartScript(); Formula repeatFormula = new Formula(new FormulaElement(ElementType.SENSOR, Sensors.OBJECT_Y.name(), null)); RepeatBrick repeatBrick = new RepeatBrick(repeatFormula); LoopEndBrick loopEndBrick = new LoopEndBrick(repeatBrick); repeatBrick.setLoopEndBrick(loopEndBrick); final int deltaY = -10; testScript.addBrick(new ChangeYByNBrick(10)); testScript.addBrick(repeatBrick); testScript.addBrick(new ChangeYByNBrick(deltaY)); testScript.addBrick(loopEndBrick); testSprite.addScript(testScript); testSprite.createStartScriptActionSequenceAndPutToMap(new HashMap<String, List<String>>()); while (!testSprite.look.getAllActionsAreFinished()) { testSprite.look.act(1.0f); } assertEquals("Executed the wrong number of times!", deltaY * 9, (int) testSprite.look.getYInUserInterfaceDimensionUnit()); } public void testNestedRepeatBrick() throws InterruptedException { final int deltaY = -10; final float delta = 0.005f; RepeatBrick repeatBrick = new RepeatBrick(REPEAT_TIMES); LoopEndBrick loopEndBrick = new LoopEndBrick(repeatBrick); repeatBrick.setLoopEndBrick(loopEndBrick); RepeatBrick nestedRepeatBrick = new RepeatBrick(REPEAT_TIMES); LoopEndBrick nestedLoopEndBrick = new LoopEndBrick(nestedRepeatBrick); nestedRepeatBrick.setLoopEndBrick(nestedLoopEndBrick); testScript.addBrick(repeatBrick); testScript.addBrick(nestedRepeatBrick); testScript.addBrick(new ChangeYByNBrick(deltaY)); testScript.addBrick(nestedLoopEndBrick); testScript.addBrick(loopEndBrick); testSprite.addScript(testScript); testSprite.createStartScriptActionSequenceAndPutToMap(new HashMap<String, List<String>>()); float timePerActCycle = 0.5f; while (!testSprite.look.getAllActionsAreFinished()) { testSprite.look.act(timePerActCycle); } testSprite.look.act(delta); assertEquals("Executed the wrong number of times!", REPEAT_TIMES * REPEAT_TIMES * deltaY, (int) testSprite.look.getYInUserInterfaceDimensionUnit()); } public void testNegativeRepeats() throws InterruptedException { Sprite testSprite = new SingleSprite("sprite"); RepeatBrick repeatBrick = new RepeatBrick(-1); SequenceAction sequence = (SequenceAction) testSprite.getActionFactory().createSequence(); repeatBrick.addActionToSequence(testSprite, sequence); RepeatAction repeatAction = (RepeatAction) sequence.getActions().get(0); boolean wait = false; while (!wait) { wait = sequence.act(1.0f); } int executedCount = (Integer) Reflection.getPrivateField(repeatAction, "executedCount"); assertEquals("Executed the wrong number of times!", 0, executedCount); } public void testZeroRepeats() throws InterruptedException { final float decoyDeltaY = -150f; final float expectedDeltaY = 150f; final RepeatAction repeatAction = (RepeatAction) testSprite.getActionFactory().createRepeatAction(testSprite, new Formula(0), testSprite.getActionFactory().createChangeYByNAction(testSprite, new Formula(decoyDeltaY))); repeatAction.act(1f); testSprite.getActionFactory().createChangeYByNAction(testSprite, new Formula(expectedDeltaY)).act(1f); int executedCount = (Integer) Reflection.getPrivateField(repeatAction, "executedCount"); assertEquals("Executed the wrong number of times!", 0, executedCount); assertEquals("Loop was executed although repeats were set to zero!", expectedDeltaY, testSprite.look.getYInUserInterfaceDimensionUnit()); } public void testBrickWithValidStringFormula() { Formula stringFormula = new Formula(String.valueOf(REPEAT_TIMES)); testWithFormula(stringFormula, testSprite.look.getYInUserInterfaceDimensionUnit() + delta * REPEAT_TIMES); } public void testBrickWithInValidStringFormula() { Formula stringFormula = new Formula(String.valueOf(NOT_NUMERICAL_STRING)); testWithFormula(stringFormula, testSprite.look.getYInUserInterfaceDimensionUnit()); } public void testNullFormula() { Action repeatedAction = testSprite.getActionFactory().createSetXAction(testSprite, new Formula(10)); Action repeatAction = testSprite.getActionFactory().createRepeatAction(testSprite, null, repeatedAction); repeatAction.act(1.0f); Object repeatCountValue = Reflection.getPrivateField(repeatAction, "repeatCountValue"); assertEquals("Null Formula should not have been possible to interpret!", 0, repeatCountValue); } public void testNotANumberFormula() { Formula notANumber = new Formula(Double.NaN); testWithFormula(notANumber, testSprite.look.getYInUserInterfaceDimensionUnit()); } private void testWithFormula(Formula formula, Float expected) { RepeatBrick repeatBrick = new RepeatBrick(formula); LoopEndBrick loopEndBrick = new LoopEndBrick(repeatBrick); repeatBrick.setLoopEndBrick(loopEndBrick); testScript.addBrick(repeatBrick); testScript.addBrick(new ChangeYByNBrick(delta)); testScript.addBrick(loopEndBrick); testSprite.addScript(testScript); testSprite.createStartScriptActionSequenceAndPutToMap(new HashMap<String, List<String>>()); while (!testSprite.look.getAllActionsAreFinished()) { testSprite.look.act(1.0f); } assertEquals("Executed the wrong number of times!", expected, testSprite.look.getYInUserInterfaceDimensionUnit()); } }