/** * 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.List; import java.util.Set; import java.util.UUID; import org.junit.Test; import static org.junit.Assert.*; import abs.frontend.analyser.SemanticConditionList; import abs.frontend.ast.*; public class ProductLineTypeAnalysisTest extends DeltaTest { @Test public void wellFormedProductLine1() { Model model = assertParseOk( "module M;" + "delta D1;" + "delta D2;" + "productline PL;" + "features A;" + "delta D1 after D2;" ); ProductLine pl = model.getProductLine(); SemanticConditionList errors = new SemanticConditionList(); /* * No delta clause for D2 */ assertFalse(ProductLineTypeAnalysisHelper.wellFormedProductLine(pl, errors)); assertEquals(1, errors.getErrorCount()); } @Test public void wellFormedProductLine2() { Model model = assertParseOk( "module M;" + "delta D1;" + "delta D2;" + "productline PL;" + "features A;" + "delta D1 after D2;" + "delta D2;" ); ProductLine pl = model.getProductLine(); SemanticConditionList errors = new SemanticConditionList(); /* * All OK */ assertTrue(ProductLineTypeAnalysisHelper.wellFormedProductLine(pl, errors)); assertEquals(0, errors.getErrorCount()); } @Test public void stronglyUnambiguousProductLine1() { Model model = assertParseOk( "module M;" + "delta D1; uses M; modifies class C { adds Unit foo() {} }" + "delta D2; modifies class M.C { adds Unit foo() {} }" + "productline PL;" + "features A;" + "delta D1;" + "delta D2 after D1;" ); ProductLine pl = model.getProductLine(); SemanticConditionList errors = new SemanticConditionList(); assertTrue(ProductLineTypeAnalysisHelper.isStronglyUnambiguous(pl, errors)); assertEquals(0, errors.getErrorCount()); } @Test public void stronglyUnambiguousProductLine2() { Model model = assertParseOk( "module M;" + "delta D1; uses M; modifies class C { adds Unit foo() {} }" + "delta D2; uses M; modifies class C { adds Unit bar() {} }" + "productline PL;" + "features A;" + "delta D1;" + "delta D2;" ); ProductLine pl = model.getProductLine(); SemanticConditionList errors = new SemanticConditionList(); /* * Both deltas are in same partition (no order specified) * They modify class C in different ways, by adding different methods */ assertTrue(ProductLineTypeAnalysisHelper.isStronglyUnambiguous(pl, errors)); assertEquals(0, errors.getErrorCount()); } @Test public void stronglyUnambiguousProductLine3() { Model model = assertParseOk( "module M;" + "productline PL;" + "features A;" ); ProductLine pl = model.getProductLine(); SemanticConditionList errors = new SemanticConditionList(); /* * No deltas, no worries */ assertTrue(ProductLineTypeAnalysisHelper.isStronglyUnambiguous(pl, errors)); assertEquals(0, errors.getErrorCount()); List<Set<String>> partition = pl.getDeltaPartition(); assertEquals(partition.size(), 0); } @Test public void stronglyUnambiguousProductLine4() { Model model = assertParseOk( "module M;" + "delta D1; uses M; modifies class C { adds Unit foo() {} }" + "delta D2; uses M; modifies class C { adds Unit foo() {} }" + "productline PL;" + "features A;" + "delta D1;" + "delta D2;" ); ProductLine pl = model.getProductLine(); SemanticConditionList errors = new SemanticConditionList(); /* Both deltas are in same partition (no order specified) * Both deltas modify the same method C.foo */ assertFalse(ProductLineTypeAnalysisHelper.isStronglyUnambiguous(pl, errors)); assertEquals(1, errors.getErrorCount()); } @Test public void stronglyUnambiguousProductLine5() { Model model = assertParseOk( "module M;" + "delta D1; uses M; adds class C {}" + "delta D2; uses M; removes class C;" + "productline PL;" + "features A;" + "delta D1;" + "delta D2;" ); ProductLine pl = model.getProductLine(); SemanticConditionList errors = new SemanticConditionList(); /* Both deltas are in same partition (no order specified) * Both deltas act on the same class C */ assertFalse(ProductLineTypeAnalysisHelper.isStronglyUnambiguous(pl, errors)); assertEquals(1, errors.getErrorCount()); } @Test public void stronglyUnambiguousProductLine6() { Model model = assertParseOk( "module M;" + "delta D1; uses M; modifies class C { adds Unit foo() {} }" + "delta D2; uses M; removes class C;" + "delta D3; uses M; adds class C {}" + "productline PL;" + "features A;" + "delta D1;" + "delta D2;" + "delta D3;" ); ProductLine pl = model.getProductLine(); SemanticConditionList errors = new SemanticConditionList(); /* All 3 deltas are in same partition * D1, D2, D3 act on the same class C */ assertFalse(ProductLineTypeAnalysisHelper.isStronglyUnambiguous(pl, errors)); assertEquals(2, errors.getErrorCount()); } @Test public void stronglyUnambiguousProductLinePerformance() { Model model = assertParseOk("module M; class C {}"); CompilationUnit cu = new CompilationUnit(); model.addCompilationUnit(cu); ProductLine pl = new ProductLine(); pl.setName("PL"); cu.setProductLine(pl); int n = 2000; for (int i=0; i<n; i++) { String id = Integer.toHexString(UUID.randomUUID().hashCode()); ModifyClassModifier cmod = new ModifyClassModifier(); cmod.setName("C"); MethodSig msig = new MethodSig(); msig.setName("m" + id); MethodImpl mimpl = new MethodImpl(); mimpl.setMethodSig(msig); abs.frontend.ast.List<MethodImpl> list = new abs.frontend.ast.List<>(); list.add(mimpl); DeltaTraitModifier dmod = new DeltaTraitModifier(new ModifyMethodModifier(new TraitSetExpr(list))); cu.addDeltaDecl(new DeltaDecl("D" + id, new abs.frontend.ast.List<DeltaParamDecl>(), new abs.frontend.ast.List<DeltaAccess>(), new abs.frontend.ast.List<ModuleModifier>(cmod))); DeltaClause dc = new DeltaClause(); Deltaspec dspec = new Deltaspec(); dspec.setDeltaID("D" + id); dc.setDeltaspec(dspec); pl.addDeltaClause(dc); } pl = model.getProductLine(); SemanticConditionList errors = new SemanticConditionList(); long startTime = System.currentTimeMillis(); assertTrue(ProductLineTypeAnalysisHelper.isStronglyUnambiguous(pl, errors)); long stopTime = System.currentTimeMillis(); //System.out.println(n + " deltas. time (ms): " + (stopTime - startTime)); } }