package de.psi.alloy4smt.ast; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; import kodkod.instance.Universe; import org.junit.Before; import org.junit.Test; import de.psi.alloy4smt.ast.PreparedCommand.IntrefSigRecord; import edu.mit.csail.sdg.alloy4.ConstList; import edu.mit.csail.sdg.alloy4.Err; import edu.mit.csail.sdg.alloy4.ErrorFatal; import edu.mit.csail.sdg.alloy4compiler.ast.Command; import edu.mit.csail.sdg.alloy4compiler.ast.Expr; import edu.mit.csail.sdg.alloy4compiler.ast.Sig; import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; import edu.mit.csail.sdg.alloy4compiler.ast.VisitQuery; import edu.mit.csail.sdg.alloy4compiler.parser.CompModule; import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; public class IntRefPreprocessorTest { private static final String simpleModuleDoc = "sig X { v: Y }\n" + "sig Y { w: X ->one X }\n"; private static final String intrefmod = "module util/intref\n" + "abstract sig IntRef { aqclass: IntRef }\n"; private static final String[] stdsigs = { "univ", "Int", "seq/Int", "String", "none" }; private CompModule module; private IntRefPreprocessor ppresult; @Before public void setUp() { module = null; ppresult = null; } private void parseModule(String doc) throws Err { Map<String,String> fm = new HashMap<String, String>(); fm.put("/tmp/x", doc); fm.put("/tmp/util/intref.als", intrefmod); module = CompUtil.parseEverything_fromFile(null, fm, "/tmp/x"); } private void preprocessModule(String doc) throws Err { parseModule(doc); ppresult = IntRefPreprocessor.processModule(module); assertStdSigsAreTheSame(module, ppresult); } private static void assertStdSigsAreTheSame(CompModule module, IntRefPreprocessor p) { Map<String, Sig> modsigs = new HashMap<String, Sig>(); Map<String, Sig> presigs = new HashMap<String, Sig>(); for (Sig s: module.getAllReachableSigs()) { modsigs.put(s.toString(), s); } for (Sig s: p.sigs) { presigs.put(s.toString(), s); } for (String name: stdsigs) { assertEquals(modsigs.get(name), presigs.get(name)); } } @Test public void retainSigsIfUtilIntrefIsNotUsed() throws Err { preprocessModule(simpleModuleDoc); ConstList<Sig> msigs = module.getAllReachableSigs(); ConstList<Sig> nsigs = ppresult.sigs; assertEquals(msigs, nsigs); assertTrue("There should be no new instance for sig X.", ppresult.sigs.contains(Helpers.getSigByName(module.getAllReachableSigs(), "this/X"))); } private void assertDeclConversion(String decl, String newDecl) throws Err { String modstr = "open util/intref\nsig A {}\nsig X { v: " + decl + " }\n"; preprocessModule(modstr); Sig sig = Helpers.getSigByName(module.getAllReachableSigs(), "this/X"); Sig.Field field = Helpers.getFieldByName(sig.getFields(), "v"); assertNotNull(field); Sig newsig = Helpers.getSigByName(ppresult.sigs, "this/X"); Sig.Field newfield = Helpers.getFieldByName(newsig.getFields(), "v"); assertNotNull(newfield); assertEquals(decl, field.decl().expr.toString()); assertEquals(newDecl, newfield.decl().expr.toString()); } @Test public void convertFieldDecl() throws Err { assertDeclConversion("one this/A", "one this/A"); assertDeclConversion("one Int", "one this/X_v_IntRef"); assertDeclConversion("univ ->one Int", "univ ->one this/X_v_IntRef"); assertDeclConversion("this/A ->one Int", "this/A ->one this/X_v_IntRef"); assertDeclConversion("this/A ->lone Int", "this/A ->lone this/X_v_IntRef"); } private void assertInvalidDecls(String decl) throws Err { String modstr = "open util/intref\nsig A {}\nsig X { v: " + decl + " }\n"; try { preprocessModule(modstr); fail(); } catch (ErrorFatal e) { assertTrue(e.msg.contains("unsupported decl")); } } @Test public void invalidFieldDecl() throws Err { //assertInvalidDecls("this/A -> Int"); assertInvalidDecls("Int -> Int"); //assertInvalidDecls("univ -> Int"); } private void assertConvFieldDecl(String sigName, String fieldName, String expDecl) { Sig sig = Helpers.getSigByName(ppresult.sigs, sigName); Sig.Field field = Helpers.getFieldByName(sig.getFields(), fieldName); assertNotNull("Field " + fieldName + " not found!", field); assertEquals(expDecl, field.decl().expr.toString()); } private void assertSigExists(String sigName) { assertNotNull("Sig " + sigName + " does not exist", Helpers.getSigByName(ppresult.sigs, sigName)); } @Test public void convertIntSigs() throws Err { preprocessModule( "open util/intref\n" + "sig X { v: Int }\n" + "sig Y { w: X ->one Int, u: Y ->one Int }"); assertFalse("A new instance for sig X should have been created", ppresult.sigs.contains(Helpers.getSigByName(module.getAllReachableSigs(), "this/X"))); assertNotNull(ppresult.intref); assertConvFieldDecl("this/X", "v", "one this/X_v_IntRef"); assertConvFieldDecl("this/Y", "w", "this/X ->one this/Y_w_IntRef"); assertConvFieldDecl("this/Y", "u", "this/Y ->one this/Y_u_IntRef"); assertSigExists("this/Y_w_IntRef"); assertSigExists("intref/IntRef"); Sig.PrimSig sig = (PrimSig) Helpers.getSigByName(ppresult.sigs, "this/Y_w_IntRef"); Sig.PrimSig intref = (PrimSig) Helpers.getSigByName(ppresult.sigs, "intref/IntRef"); assertEquals(intref, ppresult.intref); assertEquals("intref/IntRef", sig.parent.label); assertEquals(ppresult.intref, sig.parent); assertEquals(3, ppresult.intref.children().size()); assertTrue(ppresult.intref.children().contains(sig)); } @Test public void intRefBounds() throws Err { preprocessModule( "open util/intref\n" + "sig X { v: Int }\n" + "pred show {}\n" + "run show for 4 X\n" + "run show for exactly 4 X\n"); assertEquals("Run show for 4 X", module.getAllCommands().get(0).toString()); assertEquals("Run show for 4 X, exactly 4 X_v_IntRef", ppresult.commands.get(0).command.toString()); assertEquals("Run show for exactly 4 X", module.getAllCommands().get(1).toString()); assertEquals("Run show for exactly 4 X, exactly 4 X_v_IntRef", ppresult.commands.get(1).command.toString()); } @Test public void intRefBounds2() throws Err { preprocessModule( "open util/intref\n" + "sig X { v: Y ->one Int, w: X -> Y ->one Int }\n" + "sig Y {}\n" + "pred show {}\n" + "run show for 4 X, 3 Y\n"); assertEquals("Run show for 4 X, 3 Y", module.getAllCommands().get(0).toString()); assertEquals("Run show for 4 X, 3 Y, exactly 12 X_v_IntRef, exactly 48 X_w_IntRef", ppresult.commands.get(0).command.toString()); } @Test public void intRefBounds3() throws Err { preprocessModule( "open util/intref\n" + "sig X { v: Y ->one Int -> Y }\n" + "sig Y {}\n" + "pred show {}\n" + "run show for 5 X, 6 Y\n"); assertEquals("Run show for 5 X, 6 Y", module.getAllCommands().get(0).toString()); assertEquals("Run show for 5 X, 6 Y, exactly 180 X_v_IntRef", ppresult.commands.get(0).command.toString()); } @Test public void commandScopeContainsNewSig() throws Err { preprocessModule( "open util/intref\n" + "sig X { v: Int }\n" + "pred show {}\n" + "run show for 4 X\n"); final Sig oldX = Helpers.getSigByName(module.getAllReachableSigs(), "this/X"); final Sig newX = Helpers.getSigByName(ppresult.commands.get(0).sigs, "this/X"); assertNotSame(oldX, newX); assertNull(ppresult.commands.get(0).command.getScope(oldX)); assertNotNull(ppresult.commands.get(0).command.getScope(newX)); assertEquals(4, ppresult.commands.get(0).command.getScope(newX).endingScope); } @Test public void oneSigBounds() throws Err { preprocessModule( "open util/intref\n" + "one sig X { u: Int, v: Y ->one Int, w: Z ->one Int }\n" + "sig Y {}\n" + "one sig Z {}\n" + "pred show {}\n" + "run show for 4 Y\n"); assertEquals("Run show for 4 Y", module.getAllCommands().get(0).toString()); assertEquals("Run show for 4 Y, exactly 1 X_u_IntRef, exactly 4 X_v_IntRef, exactly 1 X_w_IntRef", ppresult.commands.get(0).command.toString()); Sig sigXold = Helpers.getSigByName(module.getAllReachableSigs(), "this/X"); Sig sigXnew = Helpers.getSigByName(ppresult.sigs, "this/X"); Sig sigYold = Helpers.getSigByName(module.getAllReachableSigs(), "this/Y"); Sig sigYnew = Helpers.getSigByName(ppresult.sigs, "this/Y"); assertNotNull(sigXold.isOne); assertNotNull(sigXnew.isOne); assertNull(sigYold.isOne); assertNull(sigYnew.isOne); } @Test public void implicitSigBounds() throws Err { preprocessModule( "open util/intref\n" + "sig X { v: Y ->one Int }\n" + "sig Y {}\n" + "one sig Z { u: Y ->one Int }\n" + "pred show {}\n" + "run show for 3 but 4 Y\n" + "run show for 3\n"); assertEquals("Run show for 3 but 4 Y", module.getAllCommands().get(0).toString()); assertEquals("Run show for 3 but 4 Y, exactly 12 X_v_IntRef, exactly 4 Z_u_IntRef", ppresult.commands.get(0).command.toString()); assertEquals("Run show for 3", module.getAllCommands().get(1).toString()); assertEquals("Run show for 3 but exactly 9 X_v_IntRef, exactly 3 Z_u_IntRef", ppresult.commands.get(1).command.toString()); } private static class FindAllSigs extends VisitQuery<Object> { public final List<Sig> sigs = new Vector<Sig>(); @Override public Object visit(Sig x) throws Err { sigs.add(x); return super.visit(x); } } @Test public void oldSigsAreNotReferencedAnymore() throws Err { preprocessModule( "open util/intref\n" + "sig X { v: Y ->one Int, r: Y } { all y: Y | r = y }\n" + "sig Y { f: X } { all x: X | f = x }\n" + "one sig Z { u: Y ->one Int }\n" + "fact { all x: X, y: Y | x.r = y }\n" + "pred show {}\n" + "run show for 3 but 4 Y\n"); FindAllSigs fas = new FindAllSigs(); fas.visitThis(ppresult.commands.get(0).command.formula); for (Sig sig : ppresult.sigs) { for (Expr expr : sig.getFacts()) fas.visitThis(expr); for (Field field : sig.getFields()) fas.visitThis(field.decl().expr); } assertTrue("fas.sigs = " + fas.sigs.size(), fas.sigs.size() >= 3); for (Sig sig : fas.sigs) { assertTrue("Old sig remains: " + sig.label, ppresult.sigs.contains(sig)); } } @Test public void sigFactsAreRetained() throws Err { preprocessModule( "open util/intref\n" + "sig X { v: Y ->one Int, r: Y } { all y: Y | r = y }\n" + "sig Y { f: X } { all x: X | f = x }\n" + "one sig Z { u: Y ->one Int }\n" + "pred show {}\n" + "run show for 3 but 4 Y\n"); assertTrue(Helpers.getSigByName(ppresult.sigs, "this/X").getFacts().size() > 0); assertTrue(Helpers.getSigByName(ppresult.sigs, "this/Y").getFacts().size() > 0); assertTrue(Helpers.getSigByName(ppresult.sigs, "this/Z").getFacts().size() == 0); } @Test public void unchangedFacts() throws Err { preprocessModule( "open util/intref\n" + "sig A {}\n" + "sig B { m: A -> A}\n" + "pred testeq[a: A, b: B] { let a2 = b.m[a] | a2 != a }\n" + "fact { all b: B, a: A { let a2 = a | testeq[a2, b] } }\n" + "fact { all b: B, a: A { b.m[a] = a implies b.m[a] = a else b.m[a] != a } }\n" + "pred show {}\n" + "run show for 4"); assertEquals(module.getAllReachableFacts().toString(), ppresult.commands.get(0).command.formula.toString()); } @Test public void rewriteFactsAndExtractIntExprs() throws Err { preprocessModule( "open util/intref\n" + "one sig A { v: Int }\n" + "fact { A.v.plus[2] = 4 }\n" + "fact { A.v > 0 }\n" + "pred show {}\n" + "run show for 3\n"); assertEquals("AND[int[this/A . (this/A <: v)] + 2 = 4, int[this/A . (this/A <: v)] > 0]", module.getAllReachableFacts().toString()); assertEquals( "AND[" + "IntExpr0 . (intref/IntRef <: aqclass) = this/A . (this/A <: v) . (intref/IntRef <: aqclass), " + "IntExpr1 . (intref/IntRef <: aqclass) = this/A . (this/A <: v) . (intref/IntRef <: aqclass)" + "]", ppresult.commands.get(0).command.formula.toString()); assertEquals(2, ppresult.commands.get(0).hysatExprs.size()); assertEquals("((IntExpr0$0 + 2) = 4)", ppresult.commands.get(0).hysatExprs.get(0)); assertEquals("(IntExpr1$0 > 0)", ppresult.commands.get(0).hysatExprs.get(1)); assertNotNull(Helpers.getSigByName(ppresult.commands.get(0).sigs, "IntExpr0")); assertNotNull(Helpers.getSigByName(ppresult.commands.get(0).sigs, "IntExpr1")); } @Test public void rewriteFactsWithIntExprsAndNormalExprs() throws Err { preprocessModule( "open util/intref\n" + "one sig A { v: Int }\n" + "one sig Y { y: Y }\n" + "fact { A.v.plus[2] = 4 }\n" + "fact { Y.y = Y }\n" + "pred show {}\n" + "run show for 3\n"); assertEquals("AND[int[this/A . (this/A <: v)] + 2 = 4, this/Y . (this/Y <: y) = this/Y]", module.getAllReachableFacts().toString()); assertEquals( "AND[" + "IntExpr0 . (intref/IntRef <: aqclass) = this/A . (this/A <: v) . (intref/IntRef <: aqclass), " + "this/Y . (this/Y <: y) = this/Y" + "]", ppresult.commands.get(0).command.formula.toString()); assertEquals(1, ppresult.commands.get(0).hysatExprs.size()); assertEquals("((IntExpr0$0 + 2) = 4)", ppresult.commands.get(0).hysatExprs.get(0)); } @Test public void rewriteFactsWithIntsOnLeftAndRightSide() throws Err { preprocessModule( "open util/intref\n" + "one sig A { v: Int }\n" + "one sig B { u: Int }\n" + "one sig C { m: Int }\n" + "one sig D { n: Int }\n" + "fact { A.v.plus[B.u] = 4 }\n" + "fact { C.m.plus[D.n] = 4 }\n" + "pred show {}\n" + "run show for 3\n"); assertEquals("AND[" + "int[this/A . (this/A <: v)] + int[this/B . (this/B <: u)] = 4, " + "int[this/C . (this/C <: m) + this/D . (this/D <: n)] = 4" + "]", module.getAllReachableFacts().toString()); assertEquals("AND[" + "IntExpr0 . (intref/IntRef <: aqclass) = this/A . (this/A <: v) . (intref/IntRef <: aqclass), " + "IntExpr1 . (intref/IntRef <: aqclass) = this/B . (this/B <: u) . (intref/IntRef <: aqclass), " + "IntExpr2 . (intref/IntRef <: aqclass) = this/C . (this/C <: m) . (intref/IntRef <: aqclass), " + "IntExpr3 . (intref/IntRef <: aqclass) = this/D . (this/D <: n) . (intref/IntRef <: aqclass)" + "]", ppresult.commands.get(0).command.formula.toString()); } private void assertIntexprBound(int intexprid, String expected) { List<String> atoms = new Vector<String>(); for (Sig sig : ppresult.commands.get(0).sigs) { for (int i = 0; i < 10; ++i) atoms.add(IntRefPreprocessor.atomize(sig, i)); } final Universe universe = new Universe(atoms); final Command command = ppresult.commands.get(0).command; IntrefSigRecord intexprRecord = null; for (IntrefSigRecord record : ppresult.commands.get(0).intrefRecords) { if (record.sig.label.equals("IntExpr" + intexprid)) intexprRecord = record; } assertEquals(expected, intexprRecord.getMapBounds(command, universe.factory()).toString()); } @Test public void rewriteFactsAndExtractIntExprsInQuantifiedFormula() throws Err { preprocessModule( "open util/intref\n" + "sig A { v: Int }\n" + "fact { all a: A | a.v.plus[2] = 4 }\n" + "pred show {}\n" + "run show for 3 A\n"); assertEquals("AND[(all a | a.(this/A <: v).plus[2] = 4)]", module.getAllReachableFacts().toString()); assertEquals("Run show for 3 A, exactly 3 A_v_IntRef, exactly 3 IntExpr0", ppresult.commands.get(0).command.toString()); assertEquals("AND[" + "(all a | AND[(IntExpr0 <: map) . a . (intref/IntRef <: aqclass) = " + "a . (this/A <: v) . (intref/IntRef <: aqclass)])" + "]", ppresult.commands.get(0).command.formula.toString()); assertIntexprBound(0, "[" + "[IntExpr0$0, A$0], " + "[IntExpr0$1, A$1], " + "[IntExpr0$2, A$2]" + "]"); List<String> expectedHysatExprs = new Vector<String>(); expectedHysatExprs.add("((IntExpr0$0 + 2) = 4)"); expectedHysatExprs.add("((IntExpr0$1 + 2) = 4)"); expectedHysatExprs.add("((IntExpr0$2 + 2) = 4)"); assertEquals(expectedHysatExprs, ppresult.commands.get(0).hysatExprs); } @Test public void rewriteFactsAndExtractIntExprsWithSeveralFreeVariables() throws Err { preprocessModule( "open util/intref\n" + "sig A { v: Int }\n" + "sig B { w: Int }\n" + "fact { all a: A { no b: B | a.v.plus[b.w] > 4 } }\n" + "pred show {}\n" + "run show for 3\n"); assertEquals("AND[(all a | (no b | int[a . (this/A <: v)] + " + "int[b . (this/B <: w)] > 4))]", module.getAllReachableFacts().toString()); assertEquals("Run show for 3 but exactly 3 A_v_IntRef, exactly 3 B_w_IntRef, " + "exactly 3 IntExpr0, exactly 3 IntExpr1", ppresult.commands.get(0).command.toString()); assertEquals("AND[(all a | (no b | AND[" + "(IntExpr0 <: map) . a . (intref/IntRef <: aqclass) = " + "a . (this/A <: v) . (intref/IntRef <: aqclass), " + "(IntExpr1 <: map) . b . (intref/IntRef <: aqclass) = " + "b . (this/B <: w) . (intref/IntRef <: aqclass)" + "]))]", ppresult.commands.get(0).command.formula.toString()); assertIntexprBound(0, "[" + "[IntExpr0$0, A$0], " + "[IntExpr0$1, A$1], " + "[IntExpr0$2, A$2]" + "]"); assertIntexprBound(1, "[" + "[IntExpr1$0, B$0], " + "[IntExpr1$1, B$1], " + "[IntExpr1$2, B$2]" + "]"); List<String> expectedHysatExprs = new Vector<String>(); expectedHysatExprs.add("((IntExpr0$0 + IntExpr1$0) > 4)"); expectedHysatExprs.add("((IntExpr0$0 + IntExpr1$1) > 4)"); expectedHysatExprs.add("((IntExpr0$0 + IntExpr1$2) > 4)"); expectedHysatExprs.add("((IntExpr0$1 + IntExpr1$0) > 4)"); expectedHysatExprs.add("((IntExpr0$1 + IntExpr1$1) > 4)"); expectedHysatExprs.add("((IntExpr0$1 + IntExpr1$2) > 4)"); expectedHysatExprs.add("((IntExpr0$2 + IntExpr1$0) > 4)"); expectedHysatExprs.add("((IntExpr0$2 + IntExpr1$1) > 4)"); expectedHysatExprs.add("((IntExpr0$2 + IntExpr1$2) > 4)"); assertEquals(expectedHysatExprs, ppresult.commands.get(0).hysatExprs); } @Test public void rewriteFactsAndExtractIntExprsWithSeveralFreeVariables2() throws Err { preprocessModule( "open util/intref\n" + "sig A { v: B ->one Int }\n" + "sig B { w: Int }\n" + "fact { all a: A { no b: B | a.v[b].plus[b.w] > 4 } }\n" + "pred show {}\n" + "run show for 3\n"); assertEquals("AND[(all a | (no b | AND[" + "(IntExpr0 <: map) . b . a . (intref/IntRef <: aqclass) = " + "b . a . (this/A <: v) . (intref/IntRef <: aqclass), " + "(IntExpr1 <: map) . b . (intref/IntRef <: aqclass) = " + "b . (this/B <: w) . (intref/IntRef <: aqclass)" + "]))]", ppresult.commands.get(0).command.formula.toString()); assertIntexprBound(0, "[" + "[IntExpr0$0, A$0, B$0], " + "[IntExpr0$1, A$1, B$0], " + "[IntExpr0$2, A$2, B$0], " + "[IntExpr0$3, A$0, B$1], " + "[IntExpr0$4, A$1, B$1], " + "[IntExpr0$5, A$2, B$1], " + "[IntExpr0$6, A$0, B$2], " + "[IntExpr0$7, A$1, B$2], " + "[IntExpr0$8, A$2, B$2]" + "]"); assertIntexprBound(1, "[" + "[IntExpr1$0, B$0], " + "[IntExpr1$1, B$1], " + "[IntExpr1$2, B$2]" + "]"); List<String> expectedHysatExprs = new Vector<String>(); expectedHysatExprs.add("((IntExpr0$0 + IntExpr1$0) > 4)"); expectedHysatExprs.add("((IntExpr0$0 + IntExpr1$1) > 4)"); expectedHysatExprs.add("((IntExpr0$0 + IntExpr1$2) > 4)"); expectedHysatExprs.add("((IntExpr0$1 + IntExpr1$0) > 4)"); expectedHysatExprs.add("((IntExpr0$1 + IntExpr1$1) > 4)"); expectedHysatExprs.add("((IntExpr0$1 + IntExpr1$2) > 4)"); expectedHysatExprs.add("((IntExpr0$2 + IntExpr1$0) > 4)"); expectedHysatExprs.add("((IntExpr0$2 + IntExpr1$1) > 4)"); expectedHysatExprs.add("((IntExpr0$2 + IntExpr1$2) > 4)"); expectedHysatExprs.add("((IntExpr0$3 + IntExpr1$0) > 4)"); expectedHysatExprs.add("((IntExpr0$3 + IntExpr1$1) > 4)"); expectedHysatExprs.add("((IntExpr0$3 + IntExpr1$2) > 4)"); expectedHysatExprs.add("((IntExpr0$4 + IntExpr1$0) > 4)"); expectedHysatExprs.add("((IntExpr0$4 + IntExpr1$1) > 4)"); expectedHysatExprs.add("((IntExpr0$4 + IntExpr1$2) > 4)"); expectedHysatExprs.add("((IntExpr0$5 + IntExpr1$0) > 4)"); expectedHysatExprs.add("((IntExpr0$5 + IntExpr1$1) > 4)"); expectedHysatExprs.add("((IntExpr0$5 + IntExpr1$2) > 4)"); expectedHysatExprs.add("((IntExpr0$6 + IntExpr1$0) > 4)"); expectedHysatExprs.add("((IntExpr0$6 + IntExpr1$1) > 4)"); expectedHysatExprs.add("((IntExpr0$6 + IntExpr1$2) > 4)"); expectedHysatExprs.add("((IntExpr0$7 + IntExpr1$0) > 4)"); expectedHysatExprs.add("((IntExpr0$7 + IntExpr1$1) > 4)"); expectedHysatExprs.add("((IntExpr0$7 + IntExpr1$2) > 4)"); expectedHysatExprs.add("((IntExpr0$8 + IntExpr1$0) > 4)"); expectedHysatExprs.add("((IntExpr0$8 + IntExpr1$1) > 4)"); expectedHysatExprs.add("((IntExpr0$8 + IntExpr1$2) > 4)"); assertEquals(expectedHysatExprs, ppresult.commands.get(0).hysatExprs); } private void assertIntRefEqualsTupleSet(String tuplesetstr) { final Universe universe = new Universe(ppresult.commands.get(0).getIntrefAtoms()); assertEquals(tuplesetstr, ppresult.commands.get(0).getIntRefEqualsTupleSet(universe.factory()).toString()); } @Test public void collectIntRefAtoms() throws Err { preprocessModule( "open util/intref\n" + "one sig A { v: Int, w: B ->one Int }\n" + "sig B {}\n" + "pred show {}\n" + "run show for 3\n"); assertEquals("Run show for 3 but exactly 1 A_v_IntRef, exactly 3 A_w_IntRef", ppresult.commands.get(0).command.toString()); List<String> intrefatoms = new Vector<String>(); intrefatoms.add("A_v_IntRef$0"); intrefatoms.add("A_w_IntRef$0"); intrefatoms.add("A_w_IntRef$1"); intrefatoms.add("A_w_IntRef$2"); assertEquals(intrefatoms, ppresult.commands.get(0).getIntrefAtoms()); assertIntRefEqualsTupleSet("[" + "[A_v_IntRef$0, A_w_IntRef$0], " + "[A_v_IntRef$0, A_w_IntRef$1], " + "[A_v_IntRef$0, A_w_IntRef$2], " + "[A_w_IntRef$0, A_w_IntRef$1], " + "[A_w_IntRef$0, A_w_IntRef$2], " + "[A_w_IntRef$1, A_w_IntRef$2]" + "]"); } @Test public void collectIntRefAtomsFromFacts() throws Err { preprocessModule( "open util/intref\n" + "one sig A { v: Int, w: B ->one Int }\n" + "sig B {}\n" + "fact { A.v.plus[2] = 4 }\n" + "fact { A.v > 0 }\n" + "pred show {}\n" + "run show for 3\n"); assertEquals("Run show for 3 but exactly 1 A_v_IntRef, exactly 3 A_w_IntRef, " + "exactly 1 IntExpr0, exactly 1 IntExpr1", ppresult.commands.get(0).command.toString()); List<String> intrefatoms = new Vector<String>(); intrefatoms.add("A_v_IntRef$0"); intrefatoms.add("A_w_IntRef$0"); intrefatoms.add("A_w_IntRef$1"); intrefatoms.add("A_w_IntRef$2"); intrefatoms.add("IntExpr0$0"); intrefatoms.add("IntExpr1$0"); assertEquals(intrefatoms, ppresult.commands.get(0).getIntrefAtoms()); assertIntRefEqualsTupleSet("[" + "[A_v_IntRef$0, A_w_IntRef$0], " + "[A_v_IntRef$0, A_w_IntRef$1], " + "[A_v_IntRef$0, A_w_IntRef$2], " + "[A_v_IntRef$0, IntExpr0$0], " + "[A_v_IntRef$0, IntExpr1$0], " + "[A_w_IntRef$0, A_w_IntRef$1], " + "[A_w_IntRef$0, A_w_IntRef$2], " + "[A_w_IntRef$0, IntExpr0$0], " + "[A_w_IntRef$0, IntExpr1$0], " + "[A_w_IntRef$1, A_w_IntRef$2], " + "[A_w_IntRef$1, IntExpr0$0], " + "[A_w_IntRef$1, IntExpr1$0], " + "[A_w_IntRef$2, IntExpr0$0], " + "[A_w_IntRef$2, IntExpr1$0], " + "[IntExpr0$0, IntExpr1$0]" + "]"); } @Test public void collectIntRefAtomsFromFactsWithQuantors() throws Err { preprocessModule( "open util/intref\n" + "sig A { v: Int }\n" + "fact { all a: A | a.v.plus[2] = 4 }\n" + "pred show {}\n" + "run show for 3\n"); assertEquals("Run show for 3 but exactly 3 A_v_IntRef, exactly 3 IntExpr0", ppresult.commands.get(0).command.toString()); List<String> intrefatoms = new Vector<String>(); intrefatoms.add("A_v_IntRef$0"); intrefatoms.add("A_v_IntRef$1"); intrefatoms.add("A_v_IntRef$2"); intrefatoms.add("IntExpr0$0"); intrefatoms.add("IntExpr0$1"); intrefatoms.add("IntExpr0$2"); assertEquals(intrefatoms, ppresult.commands.get(0).getIntrefAtoms()); } }