/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package edu.mit.csail.sdg.alloy4whole;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import edu.mit.csail.sdg.alloy4.A4Reporter;
import edu.mit.csail.sdg.alloy4.MailBug;
import edu.mit.csail.sdg.alloy4.SafeList;
import edu.mit.csail.sdg.alloy4.XMLNode;
import edu.mit.csail.sdg.alloy4compiler.ast.Command;
import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar;
import edu.mit.csail.sdg.alloy4compiler.ast.Sig;
import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field;
import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil;
import edu.mit.csail.sdg.alloy4compiler.ast.Module;
import edu.mit.csail.sdg.alloy4compiler.translator.A4Options;
import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution;
import edu.mit.csail.sdg.alloy4compiler.translator.A4SolutionReader;
import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod;
/** API-specific regression test suite; the larger collection of models that test both the compiler and translator are in models/tests/*.als */
final class InternalTest {
private static void check(boolean condition) throws Exception {
if (!condition) throw new RuntimeException("Assertion failure: condition should be TRUE");
}
private static void check(Object a, Object b) {
if (a==null) {
if (b!=null) throw new AssertionError("a is null, but b is "+b);
} else if (b==null) {
throw new AssertionError("b is null, but a is "+a);
} else if (!a.equals(b)) {
throw new AssertionError("a!=b\n" + "a=" + a + "\nb=" + b + "\n");
}
}
static void test1() throws Exception {
XMLNode xml = new XMLNode(new StringReader(
"<alloy builddate='unknown'>"
+ "<instance bitwidth='2' maxseq='1' command='Run Deadlock' filename='dijkstra.als'>"
+ "<sig label='univ' ID='0' builtin='yes'> <atom label='-2'/> <atom label='-1'/> <atom label='0'/> <atom label='1'/> <atom label='State$0'/> <atom label='State$1'/> <atom label='State$2'/> </sig>"
+ "<sig label='Int' ID='1' parentID='0' builtin='yes'> <atom label='-2'/> <atom label='-1'/> <atom label='0'/> <atom label='1'/> </sig>"
+ "<sig label='seq/Int' ID='2' parentID='1' builtin='yes'> <atom label='0'/> </sig>"
+ "<sig label='State' ID='5' parentID='0'> <atom label='State$0'/> <atom label='State$1'/> <atom label='State$2'/> </sig>"
+ "<field label='len' parentID='5' ID='17'>"
+ " <tuple> <atom label='State$1'/> <atom label='-2'/> </tuple>"
+ " <tuple> <atom label='State$1'/> <atom label='-1'/> </tuple>"
+ " <types> <type ID='5'/> <type ID='1'/> </types>"
+ "</field>"
+ "<skolem label='$Deadlock_s' ID='16'>"
+ " <tuple> <atom label='State$0'/> </tuple>"
+ " <types> <type ID='5'/> </types>"
+ "</skolem>"
+ "</instance>"
+ "</alloy>"));
Sig state = new Sig.PrimSig("State");
A4Solution sol = A4SolutionReader.read(Arrays.asList(state), xml);
SafeList<ExprVar> skolems = new SafeList<ExprVar>(sol.getAllSkolems());
check(skolems.size()==1);
check(skolems.get(0).label, "$Deadlock_s");
check(skolems.get(0).type(), state.type());
//
Sig state2 = new Sig.PrimSig("State");
Field field2 = state2.addField("len", Sig.SIGINT);
sol = A4SolutionReader.read(Arrays.asList(state2), xml);
SafeList<ExprVar> skolems2 = new SafeList<ExprVar>(sol.getAllSkolems());
check(skolems2.size()==1);
check(skolems2.get(0).label, "$Deadlock_s");
check(skolems2.get(0).type(), state2.type());
check(""+sol.eval(field2.cardinality()), "-2");
}
static void test2() throws Exception {
test1();
XMLNode xml = new XMLNode(new StringReader(
"<alloy builddate='unknown'>"
+ "<instance bitwidth='2' maxseq='1' command='Run Deadlock' filename='dijkstra.als'>"
+ "<sig label='univ' ID='0' builtin='yes'> <atom label='-2'/> <atom label='-1'/> <atom label='0'/> <atom label='1'/> <atom label='State$0'/> <atom label='State$1'/> <atom label='State$2'/> </sig>"
+ "<sig label='Int' ID='1' parentID='0' builtin='yes'> <atom label='-2'/> <atom label='-1'/> <atom label='0'/> <atom label='1'/> </sig>"
+ "<sig label='seq/Int' ID='2' parentID='1' builtin='yes'> <atom label='0'/> </sig>"
+ "<sig label='Act' ID='5' parentID='0'> <atom label='Act$0'/> <atom label='Act$1'/> <atom label='Act$2'/> </sig>"
+ "<skolem label='$x' ID='16'>"
+ " <tuple> <atom label='0'/> <atom label='Act$1'/> </tuple>"
+ " <types> <type ID='2'/> <type ID='5'/> </types>"
+ "</skolem>"
+ "</instance>"
+ "</alloy>"));
Sig activity = new Sig.PrimSig("Act");
A4Solution sol = A4SolutionReader.read(Arrays.asList(activity), xml);
SafeList<ExprVar> skolems = new SafeList<ExprVar>(sol.getAllSkolems());
check(skolems.size()==1);
check(skolems.get(0).label, "$x");
check(skolems.get(0).type(), Sig.SEQIDX.type().product(activity.type()));
}
static void test3() throws Exception {
XMLNode xml = new XMLNode(new StringReader(
"<alloy builddate='unknown'>"
+ "<instance bitwidth='2' maxseq='1' command='Run Deadlock' filename='dijkstra.als'>"
+ "<sig label='univ' ID='0' builtin='yes'> <atom label='-2'/> <atom label='-1'/> <atom label='0'/> <atom label='1'/> <atom label='State$0'/> <atom label='State$1'/> <atom label='State$2'/> </sig>"
+ "<sig label='Int' ID='1' parentID='0' builtin='yes'> <atom label='-2'/> <atom label='-1'/> <atom label='0'/> <atom label='1'/> </sig>"
+ "<sig label='seq/Int' ID='2' parentID='1' builtin='yes'> <atom label='0'/> </sig>"
+ "<sig label='State' ID='5' parentID='6'> <atom label='State$0'/> </sig>"
+ "<sig label='Mutex' ID='6' parentID='5'> <atom label='Mutex$0'/> </sig>"
+ "</instance>"
+ "</alloy>"));
String err = "";
try { A4SolutionReader.read(null, xml); } catch(Throwable ex) { err=ex.toString(); }
check(err.contains("cyclic inheritance"));
}
/** Displays the amount of memory taken per solution enumeration. */
public static void main2(String[] args) throws Exception {
String filename = "models/examples/algorithms/dijkstra.als";
Module world = CompUtil.parseEverything_fromFile(A4Reporter.NOP, null, filename);
A4Options options = new A4Options();
for (Command command: world.getAllCommands()) {
A4Solution ans = TranslateAlloyToKodkod.execute_command(A4Reporter.NOP, world.getAllReachableSigs(), command, options);
while(ans.satisfiable()) {
String hc = "Answer: " + ans.toString().hashCode();
System.gc();
System.gc();
System.gc();
Thread.sleep(500);
System.gc();
System.gc();
System.gc();
Thread.sleep(500);
long t = Runtime.getRuntime().totalMemory(), f = Runtime.getRuntime().freeMemory(), m = Runtime.getRuntime().maxMemory();
System.out.println(hc + " total=" + t + " free=" + f + " max="+m); System.out.flush();
ans=ans.next();
}
return;
}
}
/** Runs every test case. */
public static void main(String[] args) throws Exception {
try {
for(Method m: InternalTest.class.getDeclaredMethods()) {
String name = m.getName();
if (name.startsWith("test")) {
System.out.print("Running "+name+"..."); System.out.flush();
m.invoke(null, new Object[0]);
System.out.print(" Done.\n"); System.out.flush();
}
}
} catch(Throwable ex) {
while(ex instanceof InvocationTargetException) ex=((InvocationTargetException)ex).getCause();
System.out.println();
System.out.flush();
System.err.println("Error:\n"+MailBug.dump(ex).trim()+"\n");
System.err.flush();
System.exit(1);
}
}
}