/**
* Copyright (c) 2009-2011, The HATS Consortium. All rights reserved.
* This file is licensed under the terms of the Modified BSD License.
*/
package abs.frontend.delta;
import java.util.ArrayList;
import java.util.Arrays;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.*;
import abs.frontend.ast.*;
public class AddRemoveModifyClassesTest extends DeltaTest {
@Test
public void addClass() throws DeltaModellingException {
Model model = assertParseOk(
"module M;"
+ "delta D; uses M;"
+ "adds class C1(String s) {}"
+ "adds class C2(String s) {}"
);
DeltaDecl delta = findDelta(model, "D");
assertNotNull(delta);
assertThat(delta, instanceOf(DeltaDecl.class));
model.applyDelta(delta);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C1");
assertNotNull(cls);
assertThat(cls, instanceOf(ClassDecl.class));
assertEquals("C1", cls.getName());
cls = (ClassDecl) findDecl(model, "M", "C2");
assertNotNull(cls);
assertThat(cls, instanceOf(ClassDecl.class));
assertEquals("C2", cls.getName());
}
@Test
public void removeClass() throws DeltaModellingException {
Model model = assertParseOk(
"module M;"
+ "class C {}"
+ "delta D;"
+ "removes class M.C;"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
DeltaDecl delta = findDelta(model, "D");
assertNotNull(delta);
model.applyDelta(delta);
cls = (ClassDecl) findDecl(model, "M", "C");
assertNull(cls);
}
@Test
public void addField() throws DeltaModellingException {
Model model = assertParseOk(
"module M;"
+ "class C {}"
+ "delta D;"
+ "modifies class M.C {"
+ " adds String myField = \"hello\";"
+ "}"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getFields().getNumChild() == 0);
DeltaDecl delta = findDelta(model, "D");
assertNotNull(delta);
model.applyDelta(delta);
assertTrue(cls.getFields().getNumChild() == 1);
assertTrue(cls.getField(0).getName().equals("myField"));
}
@Test
public void removeField() throws DeltaModellingException {
Model model = assertParseOk(
"module M;"
+ "class C { String myField = \"hello\"; } "
+ "delta D;"
+ "modifies class M.C { removes String myField; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getFields().getNumChild() == 1);
assertTrue(cls.getField(0).getName().equals("myField"));
DeltaDecl delta = findDelta(model, "D");
assertNotNull(delta);
model.applyDelta(delta);
assertEquals(0, cls.getFields().getNumChild());
}
@Test
public void modifyField() throws DeltaModellingException {
// remove and re-add field with different type
Model model = assertParseOk(
"module M; "
+ "class C { String f; Unit m() { f = \"Hello\"; } } "
+ "delta D1; "
+ "modifies class M.C { removes String f; }"
+ "delta D2; "
+ "modifies class M.C { adds Int f; modifies Unit m() { f = 99; } }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
DeltaDecl d1 = findDelta(model, "D1");
DeltaDecl d2 = findDelta(model, "D2");
model.applyDeltas(new ArrayList<DeltaDecl>(Arrays.asList(d1,d2)));
assertTrue(cls.getFields().getNumChild() == 1);
assertTrue(cls.getField(0).getName().equals("f"));
assertTrue(cls.getField(0).getAccess().toString().equals("Int"));
}
@Test
public void addMethod() throws DeltaModellingException {
Model model = assertParseOk(
"module M;"
+ "class C {}"
+ "delta D;"
+ "modifies class M.C { adds Unit myMethod() {} }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
DeltaDecl delta = findDelta(model, "D");
assertNotNull(delta);
model.applyDelta(delta);
assertTrue(cls.getMethods().getNumChild() == 1);
assertTrue(cls.getMethod(0).getMethodSig().getName().equals("myMethod"));
}
@Test
public void removeMethod() throws DeltaModellingException {
Model model = assertParseOk(
"module M;"
+ "class C { Unit myMethod() {} }"
+ "delta D;"
+ "modifies class M.C { removes Unit myMethod(); }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 1);
assertTrue(cls.getMethod(0).getMethodSig().getName().equals("myMethod"));
DeltaDecl delta = findDelta(model, "D");
assertNotNull(delta);
model.applyDelta(delta);
assertTrue(cls.getMethods().getNumChild() == 0);
}
@Test
public void modifyMethod() throws DeltaModellingException {
Model model = assertParseOk(
"module M;"
+ "class C { Int myField = 0; Unit myMethod() {} } "
+ "delta D;"
+ "modifies class M.C {"
+ " modifies Unit myMethod() { myField = 1; }"
+ "}"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 1);
assertTrue(cls.getMethod(0).getMethodSig().getName().equals("myMethod"));
DeltaDecl delta = findDelta(model, "D");
assertNotNull(delta);
model.applyDelta(delta);
assertTrue(cls.getMethods().getNumChild() == 1);
assertTrue(cls.getMethod(0).getMethodSig().getName().equals("myMethod"));
// make sure the MethodImpl defined in the delta is now in the class
ModifyClassModifier cm = (ModifyClassModifier) delta.getModuleModifier(0);
DeltaTraitModifier mm = (DeltaTraitModifier)cm.getModifier(0);
ModifyMethodModifier opr = (ModifyMethodModifier)mm.getMethodModifier();
TraitSetExpr expr = (TraitSetExpr)opr.getTraitExpr();
// It's a bit of apples (FieldUse) vs. oranges (VarUse), but the strings look the same.
assertEquals(cls.getMethod(0).toString(),expr.getMethodImpl(0).toString());
}
}