/* * 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.bricks; import android.test.AndroidTestCase; import android.util.Log; import org.catrobat.catroid.ProjectManager; import org.catrobat.catroid.content.Project; import org.catrobat.catroid.content.SingleSprite; import org.catrobat.catroid.content.Sprite; import org.catrobat.catroid.content.StartScript; import org.catrobat.catroid.content.bricks.Brick; import org.catrobat.catroid.content.bricks.ChangeBrightnessByNBrick; import org.catrobat.catroid.content.bricks.ChangeColorByNBrick; import org.catrobat.catroid.content.bricks.ChangeSizeByNBrick; import org.catrobat.catroid.content.bricks.ChangeTransparencyByNBrick; import org.catrobat.catroid.content.bricks.ChangeVariableBrick; import org.catrobat.catroid.content.bricks.ChangeVolumeByNBrick; import org.catrobat.catroid.content.bricks.ChangeXByNBrick; import org.catrobat.catroid.content.bricks.ChangeYByNBrick; import org.catrobat.catroid.content.bricks.FormulaBrick; import org.catrobat.catroid.content.bricks.GlideToBrick; import org.catrobat.catroid.content.bricks.GoNStepsBackBrick; import org.catrobat.catroid.content.bricks.IfLogicBeginBrick; import org.catrobat.catroid.content.bricks.LegoNxtMotorMoveBrick; import org.catrobat.catroid.content.bricks.LegoNxtMotorTurnAngleBrick; import org.catrobat.catroid.content.bricks.LegoNxtPlayToneBrick; import org.catrobat.catroid.content.bricks.MoveNStepsBrick; import org.catrobat.catroid.content.bricks.NoteBrick; import org.catrobat.catroid.content.bricks.PlaceAtBrick; import org.catrobat.catroid.content.bricks.RepeatBrick; import org.catrobat.catroid.content.bricks.SetBrightnessBrick; import org.catrobat.catroid.content.bricks.SetColorBrick; import org.catrobat.catroid.content.bricks.SetSizeToBrick; import org.catrobat.catroid.content.bricks.SetTransparencyBrick; import org.catrobat.catroid.content.bricks.SetVariableBrick; import org.catrobat.catroid.content.bricks.SetVolumeToBrick; import org.catrobat.catroid.content.bricks.SetXBrick; import org.catrobat.catroid.content.bricks.SetYBrick; import org.catrobat.catroid.content.bricks.SpeakBrick; import org.catrobat.catroid.content.bricks.TurnLeftBrick; import org.catrobat.catroid.content.bricks.TurnRightBrick; import org.catrobat.catroid.content.bricks.UserBrickParameter; import org.catrobat.catroid.content.bricks.UserVariableBrick; import org.catrobat.catroid.content.bricks.VibrationBrick; import org.catrobat.catroid.content.bricks.WaitBrick; import org.catrobat.catroid.formulaeditor.Formula; import org.catrobat.catroid.formulaeditor.FormulaElement; import org.catrobat.catroid.formulaeditor.FormulaElement.ElementType; import org.catrobat.catroid.formulaeditor.InterpretationException; import org.catrobat.catroid.formulaeditor.UserVariable; import org.catrobat.catroid.test.utils.Reflection; import org.catrobat.catroid.test.utils.TestUtils; import java.lang.reflect.Constructor; public class BrickCloneTest extends AndroidTestCase { private static final int BRICK_FORMULA_VALUE = 1; private static final String CLONE_BRICK_FORMULA_VALUE = "2"; private static final String VARIABLE_NAME = "test_variable"; private static final String TAG = null; private Sprite sprite; @Override protected void setUp() throws Exception { super.setUp(); sprite = new SingleSprite("testSprite"); } public void testBrickCloneWithFormula() { Brick brick = new ChangeBrightnessByNBrick(new Formula(BRICK_FORMULA_VALUE)); brickClone(brick, Brick.BrickField.BRIGHTNESS_CHANGE); brick = new ChangeTransparencyByNBrick(new Formula(BRICK_FORMULA_VALUE)); brickClone(brick, Brick.BrickField.TRANSPARENCY_CHANGE); brick = new ChangeSizeByNBrick(new Formula(BRICK_FORMULA_VALUE)); brickClone(brick, Brick.BrickField.SIZE_CHANGE); brick = new ChangeVariableBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.VARIABLE_CHANGE); brick = new ChangeVolumeByNBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.VOLUME_CHANGE); brick = new ChangeXByNBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.X_POSITION_CHANGE); brick = new ChangeYByNBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.Y_POSITION_CHANGE); brick = new GoNStepsBackBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.STEPS); brick = new IfLogicBeginBrick(10); brickClone(brick, Brick.BrickField.IF_CONDITION); brick = new LegoNxtMotorMoveBrick(LegoNxtMotorMoveBrick.Motor.MOTOR_A, BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.LEGO_NXT_SPEED); brick = new LegoNxtMotorTurnAngleBrick(LegoNxtMotorTurnAngleBrick.Motor.MOTOR_A, BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.LEGO_NXT_DEGREES); brick = new LegoNxtPlayToneBrick(BRICK_FORMULA_VALUE, BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.LEGO_NXT_FREQUENCY, Brick.BrickField.LEGO_NXT_DURATION_IN_SECONDS); brick = new MoveNStepsBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.STEPS); brick = new RepeatBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.TIMES_TO_REPEAT); brick = new SetBrightnessBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.BRIGHTNESS); brick = new SetTransparencyBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.TRANSPARENCY); brick = new SetColorBrick((float) BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.COLOR); brick = new ChangeColorByNBrick((float) BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.COLOR_CHANGE); brick = new SetSizeToBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.SIZE); brick = new SetVariableBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.VARIABLE); brick = new SetVolumeToBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.VOLUME); brick = new SetXBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.X_POSITION); brick = new SetYBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.Y_POSITION); brick = new TurnLeftBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.TURN_LEFT_DEGREES); brick = new TurnRightBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.TURN_RIGHT_DEGREES); brick = new VibrationBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.VIBRATE_DURATION_IN_SECONDS); brick = new WaitBrick(BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.TIME_TO_WAIT_IN_SECONDS); brick = new PlaceAtBrick(BRICK_FORMULA_VALUE, BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.X_POSITION, Brick.BrickField.Y_POSITION); brick = new GlideToBrick(BRICK_FORMULA_VALUE, BRICK_FORMULA_VALUE, BRICK_FORMULA_VALUE); brickClone(brick, Brick.BrickField.X_DESTINATION, Brick.BrickField.Y_DESTINATION, Brick.BrickField.DURATION_IN_SECONDS); brick = new NoteBrick(String.valueOf(BRICK_FORMULA_VALUE)); brickClone(brick, Brick.BrickField.NOTE); brick = new SpeakBrick(String.valueOf(BRICK_FORMULA_VALUE)); brickClone(brick, Brick.BrickField.SPEAK); brick = new UserBrickParameter(new Formula(0)); brickClone(brick, Brick.BrickField.USER_BRICK); } public void testVariableReferencesChangeVariableBrick() throws Exception { testVariableReferences(ChangeVariableBrick.class); } public void testVariableReferencesSetVariableBrick() throws Exception { testVariableReferences(SetVariableBrick.class); } private <T extends Brick> void testVariableReferences(Class<T> typeOfBrick) throws Exception { // set up project Project project = new Project(null, TestUtils.DEFAULT_TEST_PROJECT_NAME); ProjectManager.getInstance().setProject(project); project.getDefaultScene().addSprite(sprite); StartScript script = new StartScript(); sprite.addScript(script); project.getDefaultScene().getDataContainer().addSpriteUserVariableToSprite(sprite, VARIABLE_NAME); UserVariable spriteVariable = project.getDefaultScene().getDataContainer().getUserVariable(VARIABLE_NAME, sprite); Formula formula = new Formula(new FormulaElement(ElementType.USER_VARIABLE, VARIABLE_NAME, null)); // create brick - expects: // public SetVariableBrick(Formula variableFormula, UserVariable userVariable) Constructor<T> constructor = typeOfBrick.getDeclaredConstructor(Formula.class, UserVariable.class); T toBeTestedBrick = constructor.newInstance(formula, spriteVariable); // add brick to project script.addBrick(toBeTestedBrick); // get references Sprite clonedSprite = sprite.clone(); @SuppressWarnings("unchecked") T clonedBrick = (T) clonedSprite.getScript(0).getBrick(0); UserVariable clonedVariable = project.getDefaultScene().getDataContainer().getUserVariable(VARIABLE_NAME, clonedSprite); UserVariable clonedVariableFromBrick = (UserVariable) Reflection.getPrivateField(UserVariableBrick.class, clonedBrick, "userVariable"); // check them assertNotNull("variable should be in container", clonedVariable); assertNotSame("references shouldn't be the same", spriteVariable, clonedVariable); assertNotSame("references shouldn't be the same", spriteVariable, clonedVariableFromBrick); assertEquals("references should be the same", clonedVariable, clonedVariableFromBrick); } private void brickClone(Brick brick, Brick.BrickField... brickFields) { try { Brick cloneBrick = brick.clone(); for (Brick.BrickField brickField : brickFields) { Formula brickFormula = ((FormulaBrick) brick).getFormulaWithBrickField(brickField); Formula cloneBrickFormula = ((FormulaBrick) cloneBrick).getFormulaWithBrickField(brickField); cloneBrickFormula.setRoot(new FormulaElement(ElementType.NUMBER, CLONE_BRICK_FORMULA_VALUE, null)); assertNotSame("Error - brick.clone() not working properly", brickFormula.interpretInteger(sprite), cloneBrickFormula.interpretInteger(sprite)); } } catch (CloneNotSupportedException exception) { Log.e(TAG, Log.getStackTraceString(exception)); fail("cloning the brick failed"); } catch (InterpretationException interpretationException) { Log.e(TAG, Log.getStackTraceString(interpretationException)); fail("Cloning of the brick failed: Formula interpretation failed."); } } }