/**
* 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 static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.*;
import org.junit.Test;
import abs.backend.tests.AbsASTBuilderUtil;
import abs.frontend.ast.AddMethodModifier;
import abs.frontend.ast.Annotation;
import abs.frontend.ast.Block;
import abs.frontend.ast.ClassDecl;
import abs.frontend.ast.CompilationUnit;
import abs.frontend.ast.Decl;
import abs.frontend.ast.DeltaAccess;
import abs.frontend.ast.DeltaDecl;
import abs.frontend.ast.DeltaTraitModifier;
import abs.frontend.ast.List;
import abs.frontend.ast.MethodImpl;
import abs.frontend.ast.MethodSig;
import abs.frontend.ast.Model;
import abs.frontend.ast.ModifyClassModifier;
import abs.frontend.ast.ModifyMethodModifier;
import abs.frontend.ast.ModuleModifier;
import abs.frontend.ast.SkipStmt;
import abs.frontend.ast.Stmt;
import abs.frontend.ast.TraitExpr;
import abs.frontend.ast.TraitSetExpr;
import abs.frontend.ast.RemoveMethodModifier;
public class TraitTest extends DeltaTest{
@Test
public void addAddModifierAtRuntimeBackComp(){
Model model = assertParseOk(
"module M;"
+ "class C { Unit m(){skip;} }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
MethodSig sig= AbsASTBuilderUtil.createMethodSig("n", AbsASTBuilderUtil.getUnit());
MethodImpl impl = new MethodImpl(sig, new Block(new List<Annotation>(), new List<Stmt>(new SkipStmt())), false);
AddMethodModifier opr = new AddMethodModifier(impl);
assertNotNull(opr.getMethodImpl());
ModifyClassModifier mcn = new ModifyClassModifier();
mcn.setName("M.C");
DeltaAccess acc= new DeltaAccess(cls.getModuleDecl().getName());
DeltaDecl dd = new DeltaDecl();
dd.setName("MyDelta");
dd.addDeltaAccess(acc);
dd.addModuleModifier(mcn);
mcn.addModifier(opr);
mcn.setParent(dd);
acc.setParent(dd);
opr.setParent(mcn);
sig.setParent(opr);
CompilationUnit cu = model.getCompilationUnitList().getChild(0);
cu.addDeltaDecl(dd);
dd.setParent(cu);
model.applyDelta(dd);
assertEquals(2, cls.getMethods().getNumChild());
}
@Test
public void addModifyModifierAtRuntimeBackComp(){
Model model = assertParseOk(
"module M;"
+ "class C { Unit m(){skip;} }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
MethodSig sig= AbsASTBuilderUtil.createMethodSig("m", AbsASTBuilderUtil.getUnit());
MethodImpl impl = new MethodImpl(sig, new Block(new List<Annotation>(), new List<Stmt>(new SkipStmt(),new SkipStmt())), false);
ModifyMethodModifier opr = new ModifyMethodModifier(impl);
assertNotNull(opr.getMethodImpl());
ModifyClassModifier mcn = new ModifyClassModifier();
mcn.setName("M.C");
DeltaAccess acc= new DeltaAccess(cls.getModuleDecl().getName());
DeltaDecl dd = new DeltaDecl();
dd.setName("MyDelta");
dd.addDeltaAccess(acc);
dd.addModuleModifier(mcn);
mcn.addModifier(opr);
mcn.setParent(dd);
acc.setParent(dd);
opr.setParent(mcn);
sig.setParent(opr);
CompilationUnit cu = model.getCompilationUnitList().getChild(0);
cu.addDeltaDecl(dd);
dd.setParent(cu);
model.applyDelta(dd);
assertEquals(1, cls.getMethods().getNumChild());
assertEquals(2,cls.getMethod(0).getBlock().getNumChild());
}
@Test
public void addRemoveModifierAtRuntime(){
Model model = assertParseOk(
"module M;"
+ "class C { Unit m(){skip;} }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
MethodSig sig= AbsASTBuilderUtil.createMethodSig("m", AbsASTBuilderUtil.getUnit());
List<MethodSig> l = new List<MethodSig>(sig);
RemoveMethodModifier opr = new RemoveMethodModifier(l);
ModifyClassModifier mcn = new ModifyClassModifier();
mcn.setName("M.C");
DeltaAccess acc= new DeltaAccess(cls.getModuleDecl().getName());
DeltaDecl dd = new DeltaDecl();
dd.setName("MyDelta");
dd.addDeltaAccess(acc);
dd.addModuleModifier(mcn);
mcn.addModifier(opr);
mcn.setParent(dd);
acc.setParent(dd);
opr.setParent(mcn);
sig.setParent(opr);
CompilationUnit cu = model.getCompilationUnitList().getChild(0);
cu.addDeltaDecl(dd);
dd.setParent(cu);
model.applyDelta(dd);
assertEquals(0, cls.getMethods().getNumChild());
}
@Test
public void addMethod() {
Model model = assertParseOk(
"module M;"
+ "trait T = { Unit myMethod(){ skip; } }"
+ "class C {uses T; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 1);
assertTrue(cls.getMethod(0).getMethodSig().getName().equals("myMethod"));
}
@Test
public void addTwoMethods() {
Model model = assertParseOk(
"module M;"
+ "trait T = { Unit myMethod(){ skip; } }"
+ "trait T2 = { Unit myMethod(){ skip; } }"
+ "class C {uses T; uses T2; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 2);
assertTrue(cls.getMethod(0).toString().equals(cls.getMethod(1).toString()));
assertTrue(model.getErrors().containsErrors());
}
@Test
public void modifyNonExistingMethods() {
Model model = assertParseOk(
"module M;"
+ "trait T = {} modifies { Unit myMethod(){ skip; } }"
+ "class C {uses T; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 1);
assertTrue(cls.getMethod(0).getMethodSig().getName().equals("myMethod"));
}
@Test
public void modifyExistingMethod() {
Model model = assertParseOk(
"module M; "
+ "trait T = {} modifies { Unit myMethod(){ skip; } } "
+ "class C {uses T; Unit myMethod(){ println(\"\"); } }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 1);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 2);
assertTrue(cls.getMethod(0).getMethodSig().toString().equals(cls.getMethod(1).getMethodSig().toString()));
//myMethod is added twice
}
@Test
public void modifyTwiceExistingMethod() {
Model model = assertParseOk(
"module M; "
+ "trait T = {Unit myMethod(){ println(\"\"); } } modifies { Unit myMethod(){ println(\"test\"); } } modifies { Unit myMethod(){ skip; } }"
+ "class C {uses T; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 1);
assertTrue(cls.getMethod(0).getBlock().getStmt(0) instanceof SkipStmt);
}
@Test
public void modifyTwiceTwoTraitsExistingMethod() {
Model model = assertParseOk(
"module M; "
+ "trait T = {Unit myMethod(){ println(\"\"); }} modifies { Unit myMethod(){ println(\"test\"); } }"
+ "trait T2 = T removes Unit myMethod(); adds { Unit myMethod(){ skip; } }"
+ "class C {uses T2; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 1);
assertTrue(cls.getMethod(0).getBlock().getStmt(0) instanceof SkipStmt);
}
@Test
public void addAndModifyExistingMethod() {
Model model = assertParseOk(
"module M; "
+ " trait T = {Unit myMethod(){ println(\"\"); }} modifies { Unit myMethod(){ skip; } }"
+ " class C {uses T; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 1);
assertTrue(cls.getMethod(0).getBlock().getStmt(0) instanceof SkipStmt);
}
@Test
public void addAndModifyExistingMethodInTwoClasses() {
Model model = assertParseOk(
"module M; "
+ " trait T2 = {Unit myMethod(){ println(\"\"); }}"
+ " trait T = T2 modifies { Unit myMethod(){ skip; } }"
+ " class C {uses T; }"
+ " class C2 {uses T; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
ClassDecl cls2 = (ClassDecl) findDecl(model, "M", "C2");
assertNotNull(cls2);
assertTrue(cls2.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 1);
assertTrue(cls.getMethod(0).getBlock().getStmt(0) instanceof SkipStmt);
assertTrue(cls2.getMethods().getNumChild() == 1);
assertTrue(cls2.getMethod(0).getBlock().getStmt(0) instanceof SkipStmt);
}
@Test(expected=DeltaModellingException.class)
public void removeExistingMethodInTrait() {
Model model = assertParseOk(
"module M; "
+ " trait T = {} removes Unit myMethod();"
+ " class C {uses T; Unit myMethod(){ println(\"\"); } }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 1);
model.applyTraits();
}
@Test(expected=DeltaModellingException.class)
public void removeNonExistingMethodInTrait() {
Model model = assertParseOk(
"module M;"
+ "trait T = {} removes Unit myMethod(); "
+ "class C {uses T; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
}
@Test
public void removeExistingMethodInClassSucc() {
Model model = assertParseOk(
"module M;"
+ "trait T = {Unit myMethod(){skip;}} "
+ "class C {uses T removes Unit myMethod();; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 0);
}
@Test
public void removeExistingMethodSetInClassSucc() {
Model model = assertParseOk(
"module M;"
+ "trait T = {Unit myMethod(){skip;}Unit myMethod2(){skip;}} "
+ "class C {uses T removes { Unit myMethod(); Unit myMethod2(); }; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 0);
}
@Test
public void addAndRemoveExistingMethod() {
Model model = assertParseOk(
"module M; "
+ " trait T = Unit myMethod(){ skip; } removes Unit myMethod();"
+ " class C {uses T; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 0);
}
@Test
public void addRemoveModifyMethod() {
Model model = assertParseOk(
"module M;"
+ "trait T = {Unit myMethod(){ println(\"\"); }} "
+ "trait T3 = T modifies { Unit myMethod(){ skip; }} "
+ "class C { uses T3; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 1);
assertTrue(cls.getMethod(0).getBlock().getStmt(0) instanceof SkipStmt);
}
@Test(expected=DeltaModellingException.class)
public void circularTraits1() {
Model model = assertParseOk(
"module M;"
+ "trait T = T2 adds{Unit myMethod(){ println(\"\"); }} "
+ "trait T2 = T removes Unit myMethod(); "
+ "class C {uses T2; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
}
@Test
public void circularTraitsMultiMod() {
Model model = assertParseOk(
"module M;"
+ "trait T = {Unit myMethod(){ skip; }} "
+ "trait T2 = T modifies T modifies T modifies T modifies T modifies T modifies T \n"
+ "class C {uses T2; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 1);
}
@Test
public void addModifyRemoveMethod() {
Model model = assertParseOk(
"module M;"
+ "trait T = {Unit myMethod(){ println(\"\"); }} "
+ "trait T2 = T3 removes Unit myMethod(); "
+ "trait T3 = T modifies { Unit myMethod(){ skip; }} "
+ "class C {uses T2; }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 0);
}
@Test
public void originalCallMethod() {
Model model = assertParseOk(
"module M; "
+ " trait T = {} modifies { Unit myMethod(){ original(); skip;} }"
+ " class C {uses T; Unit myMethod(){ skip; }}"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 1);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 2);
assertFalse(cls.getMethod(1).getBlock().getStmt(0) instanceof SkipStmt);
assertTrue(cls.getMethod(1).getBlock().getStmt(1) instanceof SkipStmt);
assertTrue(cls.getMethod(0).getBlock().getStmt(0) instanceof SkipStmt);
assertFalse(cls.getMethod(0).toString().equals(cls.getMethod(1).toString()));
}
@Test
public void removeInClassVsRemoveInTrait() {
Model model = assertParseOk(
"module M;"
+"trait T = { Unit x() { println(\"signature change\"); } Unit y() { skip; } }"
+"trait T2 = T removes Unit x(); adds { Unit x(Int i) { skip; } } "
+"class C { uses T2; }"
+"class C2 { uses T adds { Unit x(Int i) { skip; } } removes Unit x();;}"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
ClassDecl cls2 = (ClassDecl) findDecl(model, "M", "C2");
assertNotNull(cls2);
assertTrue(cls2.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 2);
assertTrue(cls.getMethod(0).getBlock().getStmt(0) instanceof SkipStmt);
assertTrue(cls.getMethod(1).getBlock().getStmt(0) instanceof SkipStmt);
assertTrue(cls2.getMethods().getNumChild() == 2);
assertTrue(cls2.getMethod(0).getBlock().getStmt(0) instanceof SkipStmt);
assertTrue(cls2.getMethod(1).getBlock().getStmt(0) instanceof SkipStmt);
}
@Test
public void addSameMethodsTwice() {
Model model = assertParseOk("module TestMod;"
+ "interface Inter {}"
+ "trait T2 = { "
+ " Unit driver(){"
+ " println(\"hallo\");"
+ " this.greeting();"
+ " this.printLine_1();"
+ " this.printLine_2();"
+ " this.sendoff();"
+ " }"
+ " Unit printLine_1(){println(\"I'm 1!\");}"
+ " Unit printLine_2(){println(\"I'm 2!\");}"
+ " Unit printLine_3(){println(\"I'm 3!\");}"
+ "}"
+ "class InterImpl(Inter inter) implements Inter { uses T2 removes Unit printLine_3();; }"
+ "class InterImpl2(Inter inter) implements Inter { uses T2 removes Unit printLine_3();; }"
+ ""
+ "delta D3;" + "modifies class TestMod.InterImpl{"
+ " adds Int i = 0;"
+ " adds { "
+ " Unit greeting(){println(\"hello\"); i = i + 1;} "
+ " Unit sendoff(){println(\"goodbye\"); i = i - 1;}}}"
+ "modifies class TestMod.InterImpl2{" +
" adds Int i = 0;" +
" adds { "
+ " Unit greeting(){println(\"hello\"); i = i + 1;} "
+ " Unit sendoff(){println(\"goodbye\"); i = i - 1;}}}");
ClassDecl cls = (ClassDecl) findDecl(model, "TestMod", "InterImpl");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
ClassDecl cls2 = (ClassDecl) findDecl(model, "TestMod", "InterImpl2");
assertNotNull(cls2);
assertTrue(cls2.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 3);
assertTrue(cls2.getMethods().getNumChild() == 3);
DeltaDecl delta = findDelta(model, "D3");
assertNotNull(delta);
assertThat(delta, instanceOf(DeltaDecl.class));
model.applyDelta(delta);
assertTrue(cls.getMethods().getNumChild() == 5);
assertTrue(cls2.getMethods().getNumChild() == 5);
}
@Test
public void removeSetFromDelta() {
Model model = assertParseOk("module TestMod;"
+ "interface Inter {}"
+ "trait T2 = { "
+ " Unit driver(){"
+ " println(\"hallo\");"
+ " this.greeting();"
+ " this.printLine_1();"
+ " this.printLine_2();"
+ " this.sendoff();"
+ " }"
+ " Unit printLine_1(){println(\"I'm 1!\");}"
+ " Unit printLine_2(){println(\"I'm 2!\");}"
+ " Unit printLine_3(){println(\"I'm 3!\");}"
+ "}"
+ "class InterImpl(Inter inter) implements Inter { uses T2; }"
+ ""
+ "delta D3;" + "modifies class TestMod.InterImpl{"
+ " adds Int i = 0;"
+ " removes { "
+ " Unit printLine_1(); Unit printLine_2(); Unit printLine_3(); }"
+"}");
ClassDecl cls = (ClassDecl) findDecl(model, "TestMod", "InterImpl");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 4);
DeltaDecl delta = findDelta(model, "D3");
assertNotNull(delta);
assertThat(delta, instanceOf(DeltaDecl.class));
model.applyDelta(delta);
assertTrue(cls.getMethods().getNumChild() == 1);
}
@Test
public void resolveTest() {
Model model = assertParseOk("module TestMod;"
+ "interface Inter {}"
+ "trait T = { "
+ " Unit printLine_1(){println(\"I'm 1!\");}"
+ " Unit printLine_2(){println(\"I'm 2!\");}"
+ "}"
+ "trait T2 = { "
+ " Unit printLine_2(){println(\"I'm 2!\");}"
+ " Unit printLine_3(){println(\"I'm 3!\");}"
+ "}"
+ "class InterImpl(Inter inter) implements Inter { }"
+ ""
+ "delta D3;" + "modifies class TestMod.InterImpl{"
+ " adds Int i = 0;"
+ " adds T modifies T2"
+"}");
ClassDecl cls = (ClassDecl) findDecl(model, "TestMod", "InterImpl");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
DeltaDecl delta = findDelta(model, "D3");
assertNotNull(delta);
assertThat(delta, instanceOf(DeltaDecl.class));
ModifyClassModifier mm = (ModifyClassModifier)delta.getModuleModifier(0);
DeltaTraitModifier dml = (DeltaTraitModifier) mm.getModifier(1);
AddMethodModifier mcl = (AddMethodModifier) dml.getMethodModifier();
TraitExpr expr = mcl.getTraitExpr();
TraitExpr set = expr.resolve(cls);
assertTrue(set.getChild(0).getNumChild() == 3);
}
@Test
public void resolveTest2() {
//this tests that the given delta is wrong (as we take T union T2 and thus have printLine_2 twice)
Model model = assertParseOk("module TestMod;"
+ "interface Inter {}"
+ "trait T = { "
+ " Unit printLine_1(){println(\"I'm 1!\");}"
+ " Unit printLine_2(){println(\"I'm 2!\");}"
+ "}"
+ "trait T2 = { "
+ " Unit printLine_2(){println(\"I'm 2!\");}"
+ " Unit printLine_3(){println(\"I'm 3!\");}"
+ "}"
+ "class InterImpl(Inter inter) implements Inter { }"
+ ""
+ "delta D3;" + "modifies class TestMod.InterImpl{"
+ " adds Int i = 0;"
+ " modifies T adds T2"
+"}");
ClassDecl cls = (ClassDecl) findDecl(model, "TestMod", "InterImpl");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
DeltaDecl delta = findDelta(model, "D3");
assertNotNull(delta);
assertThat(delta, instanceOf(DeltaDecl.class));
ModifyClassModifier mm = (ModifyClassModifier)delta.getModuleModifier(0);
DeltaTraitModifier dml = (DeltaTraitModifier) mm.getModifier(1);
ModifyMethodModifier mcl = (ModifyMethodModifier) dml.getMethodModifier();
TraitExpr expr = mcl.getTraitExpr();
TraitExpr set = expr.resolve(cls);
assertTrue(set.getChild(0).getNumChild() == 4);
}
@Test
public void resolveTest3() {
Model model = assertParseOk("module TestMod;"
+ "interface Inter {}"
+ "trait T = { "
+ " Unit printLine_1(){println(\"I'm 1!\");}"
+ " Unit printLine_2(){println(\"I'm 2!\");}"
+ "}"
+ "trait T2 = { "
+ " Unit printLine_2(){println(\"I'm 2!\");}"
+ " Unit printLine_3(){println(\"I'm 3!\");}"
+ "}"
+ "class InterImpl(Inter inter) implements Inter { }"
+ ""
+ "delta D3;" + "modifies class TestMod.InterImpl{"
+ " adds Int i = 0;"
+ " modifies T removes {Unit printLine_2();}"
+"}");
ClassDecl cls = (ClassDecl) findDecl(model, "TestMod", "InterImpl");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
DeltaDecl delta = findDelta(model, "D3");
assertNotNull(delta);
assertThat(delta, instanceOf(DeltaDecl.class));
ModifyClassModifier mm = (ModifyClassModifier)delta.getModuleModifier(0);
DeltaTraitModifier dml = (DeltaTraitModifier) mm.getModifier(1);
ModifyMethodModifier mcl = (ModifyMethodModifier) dml.getMethodModifier();
TraitExpr expr = mcl.getTraitExpr();
TraitExpr set = expr.resolve(cls);
assertTrue(set.getChild(0).getNumChild() == 1);
assertThat(set, instanceOf(TraitSetExpr.class));
}
@Test
public void resolveTest4() {
Model model = assertParseOk("module TestMod;"
+ "interface Inter {}"
+ "trait T = { "
+ " Unit printLine_1(){println(\"I'm 1!\");}"
+ " Unit printLine_2(){println(\"I'm 2!\");}"
+ "}"
+ "trait T2 = { "
+ " Unit printLine_2(){println(\"I'm 2!\");}"
+ " Unit printLine_3(){println(\"I'm 3!\");}"
+ "}"
+ "class InterImpl(Inter inter) implements Inter { }"
+ ""
+ "delta D3;" + "modifies class TestMod.InterImpl{"
+ " adds Int i = 0;"
+ " modifies T adds T2 removes {Unit printLine_2();}"
+"}");
ClassDecl cls = (ClassDecl) findDecl(model, "TestMod", "InterImpl");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
DeltaDecl delta = findDelta(model, "D3");
assertNotNull(delta);
assertThat(delta, instanceOf(DeltaDecl.class));
ModifyClassModifier mm = (ModifyClassModifier)delta.getModuleModifier(0);
DeltaTraitModifier dml = (DeltaTraitModifier) mm.getModifier(1);
ModifyMethodModifier mcl = (ModifyMethodModifier) dml.getMethodModifier();
TraitExpr expr = mcl.getTraitExpr();
TraitExpr set = expr.resolve(cls);
assertTrue(set.getChild(0).getNumChild() == 3);
assertThat(set, instanceOf(TraitSetExpr.class));
}
@Test
public void collapseTest() {
Model model = assertParseOk("module TestMod;"
+ "interface Inter {}"
+ "trait T = { "
+ " Unit printLine_1(){println(\"I'm 1!\");}"
+ " Unit printLine_2(){println(\"I'm 2!\");}"
+ "}"
+ "trait T2 = { "
+ " Unit printLine_2(){println(\"I'm 2!\");}"
+ "}"
+ "trait T3 = { "
+ " Unit printLine_5(){println(\"I'm 5!\");}"
+ " Unit printLine_6(){println(\"I'm 6!\");}"
+ "}"
+ "trait T4 = { "
+ " Unit printLine_7(){println(\"I'm 7!\");}"
+ " Unit printLine_8(){println(\"I'm 8!\");}"
+ "}"
+ "class InterImpl(Inter inter) implements Inter { }"
+ ""
+ "delta D3;" + "modifies class TestMod.InterImpl{"
+ " adds Int i = 0;"
+ " adds T modifies T2 removes {Unit printLine_2();}"
+ " modifies T3 adds T4 "
+"}");
ClassDecl cls = (ClassDecl) findDecl(model, "TestMod", "InterImpl");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
model.collapseTraitModifiers();
DeltaDecl delta = findDelta(model, "D3");
assertNotNull(delta);
assertThat(delta, instanceOf(DeltaDecl.class));
ModifyClassModifier mm = (ModifyClassModifier)delta.getModuleModifier(0);
assertTrue(mm.getModifierList().getNumChild() == 6);
DeltaTraitModifier dml = (DeltaTraitModifier) mm.getModifier(1);
AddMethodModifier mcl = (AddMethodModifier) dml.getMethodModifier();
TraitExpr set = mcl.getTraitExpr();
assertTrue(set.getChild(0).getNumChild() == 2);
assertThat(set, instanceOf(TraitSetExpr.class));
DeltaTraitModifier dml2 = (DeltaTraitModifier) mm.getModifier(2);
ModifyMethodModifier mcl2 = (ModifyMethodModifier) dml2.getMethodModifier();
TraitExpr set2 = mcl2.getTraitExpr();
assertTrue(set2.getChild(0).getNumChild() == 1);
assertThat(set2, instanceOf(TraitSetExpr.class));
}
@Test
public void collapseTest2() {
Model model = assertParseOk("module TestMod;"
+ "interface Inter {}"
+ "trait T = { "
+ " Unit printLine_1(){println(\"I'm 1!\");}"
+ " Unit printLine_2(){println(\"I'm 2!\");}"
+ "}"
+ "trait T2 = { "
+ " Unit printLine_2(){println(\"I'm 2!\");}"
+ "}"
+ "trait T3 = { "
+ " Unit printLine_5(){println(\"I'm 5!\");}"
+ " Unit printLine_6(){println(\"I'm 6!\");}"
+ "}"
+ "trait T4 = { "
+ " Unit printLine_7(){println(\"I'm 7!\");}"
+ " Unit printLine_8(){println(\"I'm 8!\");}"
+ "}"
+ "class InterImpl(Inter inter) implements Inter { }"
+ ""
+ "delta D3;" + "modifies class TestMod.InterImpl{"
+ " adds T modifies T2 removes Unit printLine_2();"
+ " adds Int i = 0;"
+ " modifies T3 adds T4 "
+"}");
ClassDecl cls = (ClassDecl) findDecl(model, "TestMod", "InterImpl");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
model.collapseTraitModifiers();
DeltaDecl delta = findDelta(model, "D3");
assertNotNull(delta);
assertThat(delta, instanceOf(DeltaDecl.class));
ModifyClassModifier mm = (ModifyClassModifier)delta.getModuleModifier(0);
assertTrue(mm.getModifierList().getNumChild() == 6);
DeltaTraitModifier dml = (DeltaTraitModifier) mm.getModifier(1);
AddMethodModifier mcl = (AddMethodModifier) dml.getMethodModifier();
TraitExpr set = mcl.getTraitExpr();
assertTrue(set.getChild(0).getNumChild() == 2);
assertThat(set, instanceOf(TraitSetExpr.class));
DeltaTraitModifier dml2 = (DeltaTraitModifier) mm.getModifier(2);
ModifyMethodModifier mcl2 = (ModifyMethodModifier) dml2.getMethodModifier();
TraitExpr set2 = mcl2.getTraitExpr();
assertTrue(set2.getChild(0).getNumChild() == 1);
assertThat(set2, instanceOf(TraitSetExpr.class));
}
@Test
public void collapseTest3() {
Model model = assertParseOk("module TestMod;"
+ "trait T = {"
+ "Unit printLine_0(){println(\"I'm 0!\");}"
+ "Unit printLine_1(){println(\"I'm 1!\");}"
+ "}"
+ "trait T2 = {"
+ "Unit printLine_1(){println(\"I'm 1!\");}"
+ "}"
+ "class InterImpl(Inter inter){ }"
+ ""
+ "delta D3;"
+ "modifies class TestMod.InterImpl{"
+ "adds Int i = 0;"
+ "adds T "
+ "modifies T2 "
+ "removes { Unit printLine_0(); }"
+ " removes { Unit printLine_1(); }"
+ "adds {"
+ "Unit printLine_2(){println(\"I'm 2!\");}"
+ "Unit printLine_3(){println(\"I'm 3!\");}"
+ "}"
+ "removes { Unit printLine_2(); }"
+ "removes { Unit printLine_3(); }"
+ "}"
);
ClassDecl cls = (ClassDecl) findDecl(model, "TestMod", "InterImpl");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 0);
model.applyTraits();
model.collapseTraitModifiers();
DeltaDecl delta = findDelta(model, "D3");
assertNotNull(delta);
assertThat(delta, instanceOf(DeltaDecl.class));
ModifyClassModifier mm = (ModifyClassModifier)delta.getModuleModifier(0);
assertTrue(mm.getModifierList().getNumChild() == 8);
DeltaTraitModifier dml = (DeltaTraitModifier) mm.getModifier(1);
AddMethodModifier mcl = (AddMethodModifier) dml.getMethodModifier();
TraitExpr set = mcl.getTraitExpr();
assertTrue(set.getChild(0).getNumChild() == 2);
assertThat(set, instanceOf(TraitSetExpr.class));
DeltaTraitModifier dml2 = (DeltaTraitModifier) mm.getModifier(2);
ModifyMethodModifier mcl2 = (ModifyMethodModifier) dml2.getMethodModifier();
TraitExpr set2 = mcl2.getTraitExpr();
assertTrue(set2.getChild(0).getNumChild() == 1);
assertThat(set2, instanceOf(TraitSetExpr.class));
}
@Test
public void frameTest() {
Model model = assertParseOk(
"module M;"
+ " interface I { Unit x(); Unit foo(); Unit bar(); }"
+ " trait T = Unit x() { this.foo(); original(); this.bar(); }"
+ " trait T2 = { Unit x() { println(\"T2\"); } } modifies T"
+ " trait T3 = { Unit x() { println(\"T3\"); } } modifies T"
+ " class C implements I {"
+ " Int i = 0;"
+ " uses T2;"
+ " Unit foo(){ i = i+1; }"
+ " Unit bar(){ i = i-1; }"
+ " }"
+ " class C2 implements I {"
+ " Int i = 0;"
+ " uses T3;"
+ " Unit foo(){ i = i-1; }"
+ " Unit bar(){ i = i+1; }"
+ " }"
);
ClassDecl cls = (ClassDecl) findDecl(model, "M", "C");
assertNotNull(cls);
assertTrue(cls.getMethods().getNumChild() == 2);
model.applyTraits();
assertTrue(cls.getMethods().getNumChild() == 4);
}
}