package org.jmlspecs.openjmltest.testcases; import org.jmlspecs.openjmltest.RacBase; import org.junit.Test; /** These tests exercise the RAC checking. They compile a test class * using RAC and then execute the resulting program, catching that * programs output. All the tests here have valid JML - they are testing * whether the RAC translations work correctly. * @author David R. Cok * */ public class racnewLoops extends RacBase { /** Sets the classpath used for these tests. The bin in the classpath * brings in the currently compiled runtime classes (so we don't have * to build jmlruntime.jar) */ String[] ordrac = new String[]{jdk, "-ea", "-classpath","bin"+z+"../OpenJML/bin-runtime"+z+"testdata",null}; @Override public void setUp() throws Exception { rac = ordrac; jdkrac = false; //noCollectDiagnostics = true; print = true; super.setUp(); //main.addOptions("-verboseness=4"); expectedNotes = 0; } // FIXME - needs more tests with break and continue, including nested loops // Also tests with \index and \values @Test public void testForLoop2() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + " m(); System.out.println(\"END\"); } \n" + " static void m() { \n" + " //@ loop_invariant i <9 ; \n" + " //@ decreases 10-i; \n" + " for (int i=0; i<10; i++) ; \n" + "} " + "}" ,"/tt/TestJava.java:4: JML loop invariant is false at end of loop body" ,"/tt/TestJava.java:4: JML loop invariant is false at beginning of loop body" ,"/tt/TestJava.java:4: JML loop invariant is false at end of loop body" ,"/tt/TestJava.java:4: JML loop invariant is false at beginning of loop body" ,"END" ); } @Test public void testForLoop() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + " m(); System.out.println(\"END\"); } \n" + " static void m() { \n" + " //@ loop_invariant i <= 10 ; \n" + " //@ decreases 7-i; \n" + " for (int i=0; i<10; i++) ; \n" + "} " + "}" ,"/tt/TestJava.java:5: JML loop variant is negative" ,"/tt/TestJava.java:5: JML loop variant is negative" ,"END" ); } @Test public void testForLoopIndex() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + " m(); System.out.println(\"END\"); } \n" + " static void m() { \n" + " //@ loop_invariant i == \\index ; \n" + " //@ decreases 10-\\index; \n" + " for (int i=0; i<10; i++) ; \n" + "} " + "}" ,"END" ); } @Test public void testForNested() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + " m(); System.out.println(\"END\"); } \n" + " static void m() { \n" + " //@ loop_invariant i <= 10 ; \n" + " for (int i=0; i<10; i++) {\n" + " //@ ghost int save = \\index;\n" + " //@ loop_invariant \\index <= save; \n" + " for (int j=0; j<i; j++) {" + " ; \n" + " }\n" + " }\n" + " } " + "}" ,"END" ); } @Test public void testForEachLoop() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + " m(); System.out.println(\"END\"); } \n" + " static void m() { \n" + " int[] a = new int[10];\n" + " //@ ghost int i = 0; \n" + " //@ loop_invariant i <= a.length ; \n" + " //@ decreases a.length-i; \n" + " for (int j: a) { \n" + " //@ set i = i + 1;\n" + " }\n" + "} " + "}" ,"END" ); } @Test public void testForEachLoop2() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + " m(); System.out.println(\"END\"); } \n" + " static void m() { \n" + " int[] a = new int[10];\n" + " //@ ghost int i = 0; \n" + " //@ loop_invariant i < a.length ; \n" + " //@ decreases a.length-i-2; \n" + " for (int j: a) { \n" + " //@ set i = i + 1;\n" + " }\n" + "} " + "}" ,"/tt/TestJava.java:7: JML loop variant is negative" ,"/tt/TestJava.java:6: JML loop invariant is false at end of loop body" ,"/tt/TestJava.java:6: JML loop invariant is false at beginning of loop body" ,"END" ); } @Test public void testLoop() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + "m(5); m(0); System.out.println(\"END\"); } \n" + " static void m(int i) { \n" + " //@ loop_invariant i>= 0; \n" + " //@ decreases i; \n" + " while (i>0) --i; \n" + "} " + "}" ,"END" ); } @Test public void testLoopIndex() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + "m(5); m(0); System.out.println(\"END\"); } \n" + " static void m(int i) { \n" + " //@ loop_invariant i + \\index == \\old(i); \n" + " //@ decreases i; \n" + " while (i>0) --i; \n" + "} " + "}" ,"END" ); } @Test public void testLoop2() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + "m(5); m(0); m(-1); System.out.println(\"END\"); } \n" + " static void m(int i) { \n" + " System.out.println(\"VALUE \" + i); \n" + " //@ loop_invariant i>= 0; \n" + " //@ decreases i; \n" + " while (i>=0) --i; \n" + "} " + "}" ,"VALUE 5" ,"/tt/TestJava.java:5: JML loop invariant is false at end of loop body" ,"/tt/TestJava.java:5: JML loop invariant is false at beginning of loop body" ,"VALUE 0" ,"/tt/TestJava.java:5: JML loop invariant is false at end of loop body" ,"/tt/TestJava.java:5: JML loop invariant is false at beginning of loop body" ,"VALUE -1" ,"/tt/TestJava.java:5: JML loop invariant is false before entering loop" ,"/tt/TestJava.java:5: JML loop invariant is false at beginning of loop body" ,"END" ); } @Test public void testLoop3() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + "m(5); System.out.println(\"END\"); } \n" + " static void m(int i) { \n" + " //@ loop_invariant i>= 0; \n" + " //@ decreases i-2; \n" + " while (i>0) --i; \n" + "} " + "}" ,"/tt/TestJava.java:5: JML loop variant is negative" ,"END" ); } @Test public void testLoop4() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + "m(1); System.out.println(\"END\"); } \n" + " static void m(int i) { \n" + " //@ loop_invariant i>= 0; \n" + " //@ decreases 10-i; \n" + " while (i>0) --i; \n" + "} " + "}" ,"/tt/TestJava.java:5: JML loop variant does not decrease" ,"END" ); } @Test public void testLoop5() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + "m(7); System.out.println(\"END\"); } \n" + " static void m(int i) { \n" + " //@ loop_invariant i>= 0; \n" + " //@ decreases i; \n" + " while (i>0) { System.out.println(\"VALUE \" + i); \n" + " --i; \n" + " if (i == 4) continue;\n" + " --i; }" + "} " + "}" ,"VALUE 7" ,"VALUE 5" ,"VALUE 4" ,"VALUE 2" ,"END" ); } @Test public void testDoLoop() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + "m(5); m(1); System.out.println(\"END\"); } \n" + " static void m(int i) { \n" + " //@ loop_invariant i>= 0; \n" + " //@ decreases i; \n" + " do { --i; } while (i>0); \n" + "} " + "}" ,"END" ); } @Test public void testDoLoopIndex() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + "m(5); m(1); System.out.println(\"END\"); } \n" + " static void m(int i) { \n" + " //@ loop_invariant i>= 0; \n" + " //@ decreases i; \n" + " /*@ loop_invariant i + \\index == \\old(i); */" + " do { --i; } while (i>0); \n" + "} " + "}" ,"END" ); } @Test public void testDoLoopIndexBad() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + "m(1); System.out.println(\"END\"); } \n" + " static void m(int i) { \n" + " //@ decreases i; \n" + " /*@ loop_invariant i + \\index == \\old(i); */" + " do { --i; --i; } while (i>0); \n" + " //@ assert i == -1;\n" + "} " + "}" ,"END" ); } @Test public void testDoLoop2() { helpTCX("tt.TestJava","package tt; public class TestJava { public static void main(String[] args) { \n" + "m(5); m(0); m(-1); System.out.println(\"END\"); } \n" + " static void m(int i) { \n" + " System.out.println(\"VALUE \" + i); \n" + " //@ loop_invariant i>= 0; \n" + " //@ decreases i; \n" + " do { --i; } while (i>=0); \n" + "} " + "}" ,"VALUE 5" ,"VALUE 0" ,"VALUE -1" ,"/tt/TestJava.java:5: JML loop invariant is false before entering loop" ,"/tt/TestJava.java:5: JML loop invariant is false at beginning of loop body" ,"/tt/TestJava.java:6: JML loop variant is negative" ,"END" ); } @Test public void testForIter1() { helpTCX("tt.A","package tt; class A { public static void main(String[] args) { java.util.List<Integer> list = new java.util.LinkedList<Integer>(); list.add(0); m(list); }" +"static void m(java.util.List<Integer> list) { \n " +"int sum = 0; \n" +"//@ loop_invariant sum >= 0; \n" +"for (int o: list) { sum += o; } \n" +"//@ assert sum >= 0; \n" +"}}" ); } @Test public void testForIter1bad() { helpTCX("tt.A","package tt; class A { public static void main(String[] args) { java.util.List<Integer> list = new java.util.LinkedList<Integer>(); list.add(0); m(list);}" +"static void m(java.util.List<Integer> list) { \n " +"int sum = 0; \n" +"//@ loop_invariant sum >= 0; \n" +"for (int o: list) { sum += o; } \n" +"//@ assert sum > 0; \n" +"}}" ,"/tt/A.java:5: JML assertion is false" ); } @Test public void testForEach4() { helpTCX("tt.A","package tt; class A { public static void main(String[] args) { Integer[] aa = new Integer[]{1,2,3}; m(aa); }" +"static void m(Integer[] list) { \n " +"int sum = 0; \n" +"//@ loop_invariant sum >= 0; \n" +"for (int o: list) { /*@ assume o >= 0; */ sum += o; } \n" +"//@ assert sum >= 0; \n" +"}}" ); } @Test public void testForEach4bad() { helpTCX("tt.A","package tt; class A { public static void main(String[] args) { Integer[] aa = new Integer[]{0,0,0}; m(aa); }" +"static void m(Integer[] list) { \n " +"int sum = 0; \n" +"//@ loop_invariant sum >= 0; \n" +"for (int o: list) { /*@ assume o >= 0; */ sum += o; } \n" +"//@ assert sum > 0; \n" +"}}" ,"/tt/A.java:5: JML assertion is false" ); } }