static void testEpochs() {
    String query =
        "SP(int n:0..2000000,int d).\n"
            + "Edge(int s,int t).\n"
            + "Foo(int n, int a).\n"
            + "SP(t,d) :- Edge(1,t), d=1 .\n"
            + "SP(t,$min(d)) :- SP(p,d1), Edge(p,t), d=d1+1 .\n"
            + "Foo(a, b) :- SP(a,b).\n"
            + "Edge(n1,n2) :- n1=2, n2=20.\n";
    Parser p = new Parser();
    p.parse(query);
    Analysis an = new Analysis(p);
    an.run();
    List<Epoch> epochs = an.getEpochs();

    Assert.true_(epochs.size() == 3);
    Epoch e = epochs.get(0);
    Assert.true_(e.getRuleCompNum() == 1);
    Rule edgeLoad = e.getRuleComps().get(0).get(0);
    Assert.true_(edgeLoad.getHead().name().equals("Edge"));

    e = epochs.get(1);
    Assert.true_(e.getRuleCompNum() == 1);
    Rule sp = e.getRuleComps().get(0).get(0);
    Assert.true_(sp.getHead().name().equals("SP") && sp.getHead().hasFunctionParam());
    e = epochs.get(2);
    Assert.true_(e.getRuleCompNum() == 1);
    Rule foo = e.getRuleComps().get(0).get(0);
    Assert.true_(foo.getHead().name().equals("Foo"));
  }
  static void testEpochRecursive() {
    String query =
        "Edge(int s:1..35000, (int t)).\n"
            + "SP(int x:1..35000, int dist).\n"
            + "Edge(s, t) :- s=1,t=2.\n"
            + "SP(s, d) :- s=1, d=1.\n"
            + "SP(t, $min(d)) :- SP(s, d1), Edge(s, t), d=d1+1.\n"
            + "?- SP(5, d).\n";
    Parser p = new Parser();
    p.parse(query);
    Analysis an = new Analysis(p);
    an.run();
    List<Epoch> epoch = an.getEpochs();

    Assert.true_(epoch.size() == 2);
    Epoch s = epoch.get(0);
    Assert.true_(s.getRuleCompNum() == 1);
    Rule edgeLoad = s.getRuleComps().get(0).get(0);
    Assert.true_(edgeLoad.getHead().name().equals("Edge"));
  }
  static void testVariables() {
    String query =
        "Edge(int s,int t).\n"
            + "Foo(int f,int a, int b).\n"
            + "Foo(a, b,d) :- Foo(a,b,c), Edge(b,d).\n";
    Parser p = new Parser(query);
    p.parse();

    Assert.true_(p.getRules().size() == 1);
    Analysis analysis = new Analysis(p);
    analysis.run();

    Rule r = p.getRules().get(0);
    Predicate p0 = r.getBodyP().get(0);
    Predicate p1 = r.getBodyP().get(1);
    Variable b1 = (Variable) p0.params.get(0);
    Variable b2 = (Variable) p1.first();
    Assert.true_(b1 == b2, "expecting the same instance");
    Variable b3 = (Variable) r.getHead().params.get(0);
    Assert.true_(b1 == b3, "expecting the same instance");
  }
  static void testPrivatization() {
    String query =
        "Edge(int s:0..100000, (int t)).\n"
            + "Clique(int x:10, int y, int z) indexby x.\n"
            + "Clique(x,y,z):-Edge(x,y), Edge(y, z), Edge(z, s).\n";

    Parser p = new Parser();
    p.parse(query);
    Analysis an = new Analysis(p);
    an.run();
    List<Epoch> epochs = an.getEpochs();
    Epoch e = epochs.get(0);

    List<Rule> rules = e.getRules();
    boolean hasPrivateTable = false;
    for (Rule r : rules) {
      Map<String, Table> tableMap = an.getTableMap();
      Table t = tableMap.get(r.getHead().name());
      if (t instanceof PrivateTable) hasPrivateTable = true;
    }
    Assert.true_(hasPrivateTable);
  }