package org.jmlspecs.openjmltest.testcases;
import org.jmlspecs.openjmltest.EscBase;
import org.junit.Assume;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.ParameterizedWithNames;
@RunWith(ParameterizedWithNames.class)
public class escall3 extends EscBase {
public escall3(String option, String solver) {
super(option,solver);
}
@Override
public void setUp() throws Exception {
//noCollectDiagnostics = true;
super.setUp();
//print = true;
}
@Test
public void testSimple() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" \n"
+" public void m1bad(int i) {\n"
+" //@ assert i>0 ;\n"
+" }\n"
+" //@ requires i>=0;\n"
+" public void m2bad(int i) {\n"
+" //@ assert i>0 ;\n"
+" }\n"
+" //@ requires i>=0;\n"
+" //@ ensures \\result>0;\n"
+" public int m3bad(int i) {\n"
+" return i ;\n"
+" }\n"
+" public void m1good(int i) {\n"
+" //@ assume i>0 ;\n"
+" //@ assert i>0 ;\n"
+" }\n"
+" //@ requires i>0;\n"
+" public void m2good(int i) {\n"
+" //@ assert i>=0 ;\n"
+" }\n"
+" //@ requires i>=0;\n"
+" //@ ensures \\result>=0;\n"
+" public int m3good(int i) {\n"
+" return i ;\n"
+" }\n"
+" //@ requires i>0;\n"
+" //@ also\n"
+" //@ requires i==0;\n"
+" public void m4good(int i) {\n"
+" //@ assert i>=0 ;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:5: warning: The prover cannot establish an assertion (Assert) in method m1bad",9
,"/tt/TestJava.java:9: warning: The prover cannot establish an assertion (Assert) in method m2bad",9
,"/tt/TestJava.java:14: warning: The prover cannot establish an assertion (Postcondition) in method m3bad",5
,"/tt/TestJava.java:12: warning: Associated declaration",7
);
}
@Test
public void testFieldAccess() {
main.addOptions("-checkFeasibility=none");
helpTCX("tt.TestJava","package tt; import org.jmlspecs.annotation.*; \n"
+"public class TestJava { \n"
+" int f; \n"
+" public void m1bad(TestJava o) {\n"
+" //@ assume o.f >0 ;\n"
+" //@ assert f > 0 ;\n"
+" }\n"
+" public void m2bad(@Nullable TestJava o) {\n"
+" //@ assume o.f >0 ;\n"
+" }\n"
+" public void m1good(TestJava o) {\n"
+" //@ assume o.f >0 ;\n"
+" //@ assume o == this ;\n"
+" //@ assert f > 0 ;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:6: warning: The prover cannot establish an assertion (Assert) in method m1bad",9
,"/tt/TestJava.java:9: warning: The prover cannot establish an assertion (UndefinedNullDeReference) in method m2bad",17
);
}
@Test
public void testArrayAccess() {
helpTCX("tt.TestJava","package tt; \n"
+"import org.jmlspecs.annotation.*; \n"
+"public class TestJava { \n"
+" //@ requires a.length > 5; \n"
+" public void m1bad(@Nullable int[] a) {\n"
+" //@ assume a[1] == 0 ;\n"
+" }\n"
+" //@ requires a != null; \n"
+" public void m2bad(int[] a) {\n"
+" //@ assume a[1] == 0 ;\n"
+" }\n"
+" //@ requires a != null; \n"
+" //@ requires a.length > 5; \n"
+" public void m3bad(int[] a) {\n"
+" //@ assume a[-1] == 0 ;\n"
+" }\n"
+" //@ requires a != null; \n"
+" //@ requires a.length > 5; \n"
+" //@ requires b.length > 5; \n"
+" public void m4bad(int[] a, int[] b) {\n"
+" //@ assume a[1] == 5 ;\n"
+" //@ assert b[1] == 5 ;\n"
+" }\n"
+" //@ requires a != null; \n"
+" //@ requires a.length > 5; \n"
+" public void m1good(int[] a, int[] b) {\n"
+" //@ assume a[1] == 5 ;\n"
+" //@ assume a == b ;\n"
+" //@ assert b[1] ==5 ;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:4: warning: The prover cannot establish an assertion (UndefinedNullDeReference) in method m1bad",17
,"/tt/TestJava.java:10: warning: The prover cannot establish an assertion (UndefinedTooLargeIndex) in method m2bad",17
,"/tt/TestJava.java:15: warning: The prover cannot establish an assertion (UndefinedNegativeIndex) in method m3bad",17
,"/tt/TestJava.java:22: warning: The prover cannot establish an assertion (Assert) in method m4bad",9
);
}
@Test
public void testArrayAccess1() {
helpTCX("tt.TestJava","package tt; \n"
+" import org.jmlspecs.annotation.*; \n"
+"@NullableByDefault public class TestJava { \n"
+" public void m1() {\n"
+" int[] a = null;\n"
+" a[0] = 0;\n" // ERROR
+" }\n"
+" public void m2() {\n"
+" int[] a = null;\n"
+" int i = (a)[0];\n" // ERROR
+" }\n"
+"}"
,"/tt/TestJava.java:6: warning: The prover cannot establish an assertion (PossiblyNullDeReference) in method m1",6
,"/tt/TestJava.java:10: warning: The prover cannot establish an assertion (PossiblyNullDeReference) in method m2",16
);
}
@Test
public void testArrayAssign() {
helpTCX("tt.TestJava","package tt; \n"
+"import org.jmlspecs.annotation.*; \n"
+"public class TestJava { \n"
+" //@ requires a.length > 5; \n"
+" public void m1bad(@Nullable int[] a) {\n"
+" a[1] = 0 ;\n"
+" }\n"
+" //@ requires a != null; \n"
+" public void m2bad(int[] a) {\n"
+" a[1] = 0 ;\n"
+" }\n"
+" //@ requires a != null; \n"
+" //@ requires a.length > 5; \n"
+" public void m3bad(int[] a) {\n"
+" a[-1] = 0 ;\n"
+" }\n"
+" //@ requires a != null; \n"
+" //@ requires a.length > 5; \n"
+" //@ requires b.length > 5; \n"
+" public void m4bad(int[] a, int[] b) {\n"
+" a[1] = 5 ;\n"
+" //@ assert b[1] ==5 ;\n"
+" }\n"
+" //@ requires a != null; \n"
+" //@ requires a.length > 5; \n" // Line 25
+" public void m1good(int[] a, int[] b) {\n"
+" a[1] = 5;\n"
+" //@ assume a == b ;\n"
+" //@ assert b[1] ==5 ;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:4: warning: The prover cannot establish an assertion (UndefinedNullDeReference) in method m1bad",17
,"/tt/TestJava.java:10: warning: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method m2bad",6
,"/tt/TestJava.java:15: warning: The prover cannot establish an assertion (PossiblyNegativeIndex) in method m3bad",6
,"/tt/TestJava.java:22: warning: The prover cannot establish an assertion (Assert) in method m4bad",9
);
}
@Test
public void testArrayAssign1() {
helpTCX("tt.TestJava","package tt; \n"
+" import org.jmlspecs.annotation.*; \n"
+"@NullableByDefault public class TestJava { \n"
+" int i; static int j[];\n"
+" //@ requires a.length > 3; \n"
+" //@ assignable \\everything; \n"
+" public int m0bada(int[] a) {\n"
+" a[1] = 1;\n"
+" return a[0];\n"
+" }\n"
+" //@ requires a != null; \n"
+" //@ assignable \\everything; \n"
+" public int m0badb(int[] a) {\n"
+" a[1] = 1;\n"
+" return a[0];\n"
+" }\n"
+" //@ requires a != null && a.length > 3; \n"
+" //@ assignable \\everything; \n"
+" //@ ensures \\result == \\old(a[0]); \n"
+" public int m0badc(int[] a) {\n"
+" a[-1] = 1;\n"
+" return a[0];\n"
+" }\n"
+" //@ requires a != null && a.length > 3; \n"
+" //@ assignable \\everything; \n"
+" //@ ensures \\result == \\old(a[0]); \n" // Line 26
+" public int m1good(int[] a) {\n"
+" a[1] = 1;\n"
+" return a[0];\n"
+" }\n"
+" //@ requires a != null && a.length > 3 && i >= 0 && i <= 1; \n"
+" //@ assignable \\everything; \n"
+" //@ ensures \\result == \\old(a[0]); \n"
+" public int m1bad(int[] a, int i) {\n"
+" a[i] = 1;\n"
+" return a[0];\n"
+" }\n"
+"}"
,"/tt/TestJava.java:5: warning: The prover cannot establish an assertion (UndefinedNullDeReference) in method m0bada",17
,"/tt/TestJava.java:14: warning: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method m0badb",6
,"/tt/TestJava.java:21: warning: The prover cannot establish an assertion (PossiblyNegativeIndex) in method m0badc",6
,"/tt/TestJava.java:36: warning: The prover cannot establish an assertion (Postcondition) in method m1bad",5
,"/tt/TestJava.java:33: warning: Associated declaration",7
);
}
@Test
public void testFieldAssign() {
main.addOptions("-checkFeasibility=none");
helpTCX("tt.TestJava","package tt; import org.jmlspecs.annotation.*; \n"
+"public class TestJava { \n"
+" int f; \n"
+" public void m1bad(TestJava o) {\n"
+" o.f = 1 ;\n"
+" //@ assert f > 0 ;\n"
+" }\n"
+" public void m2bad(@Nullable TestJava o) {\n"
+" o.f = 1 ;\n"
+" // @ assert f > 0 ;\n"
+" }\n"
+" public void m1good(TestJava o) {\n"
+" o.f = 1 ;\n"
+" //@ assume o == this ;\n"
+" //@ assert f > 0 ;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:6: warning: The prover cannot establish an assertion (Assert) in method m1bad",9
,"/tt/TestJava.java:9: warning: The prover cannot establish an assertion (PossiblyNullDeReference) in method m2bad",6
);
}
@Test
public void testFieldAssign1() {
helpTCX("tt.TestJava","package tt; \n"
+" import org.jmlspecs.annotation.*; \n"
+"public class TestJava { \n"
+" int i; static int j;\n"
+" //@ assignable \\everything; \n"
+" //@ ensures \\result == 2; \n"
+" public int m1bad(boolean b) {\n"
+" i = 1;\n"
+" if (b) i = 2;\n"
+" return i;\n"
+" }\n"
+" //@ assignable \\everything; \n"
+" //@ ensures \\result == 10; \n"
+" public int m2bad(boolean b) {\n"
+" j = 1;\n"
+" if (b) TestJava.j = TestJava.j + this.j + j;\n"
+" if (b) tt.TestJava.j = TestJava.j + this.j + j;\n"
+" if (b) this.j = j + 1;\n"
+" return tt.TestJava.j;\n"
+" }\n"
+" //@ requires o != null; \n"
+" //@ assignable \\everything; \n"
+" //@ ensures \\result == 1; \n"
+" public int m3bad(TestJava o) {\n"
+" o.i = 1;\n"
+" i = 2;\n"
+" return o.i;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:10: warning: The prover cannot establish an assertion (Postcondition) in method m1bad",5
,"/tt/TestJava.java:6: warning: Associated declaration",7
,"/tt/TestJava.java:19: warning: The prover cannot establish an assertion (Postcondition) in method m2bad",5
,"/tt/TestJava.java:13: warning: Associated declaration",7
,"/tt/TestJava.java:27: warning: The prover cannot establish an assertion (Postcondition) in method m3bad",5
,"/tt/TestJava.java:23: warning: Associated declaration",7
);
}
@Test
public void testFieldAssign2() {
helpTCX("tt.TestJava","package tt; \n"
+" import org.jmlspecs.annotation.*; \n"
+"public class TestJava { \n"
+" int i; static int j;\n"
+" //@ assignable \\everything; \n"
+" //@ ensures b ==> \\result == 2; \n"
+" public int m1good(boolean b) {\n"
+" i = 1;\n"
+" if (b) i = 2;\n"
+" return i;\n"
+" }\n"
+" //@ assignable \\everything; \n"
+" //@ ensures b ==> \\result == 10; \n"
+" public int m2good(boolean b) {\n"
+" j = 1;\n"
+" if (b) TestJava.j = TestJava.j + this.j + j;\n"
+" if (b) tt.TestJava.j = TestJava.j + this.j + j;\n"
+" if (b) this.j = j + 1;\n"
+" return tt.TestJava.j;\n"
+" }\n"
+" //@ requires this != o && o != null; \n"
+" //@ assignable \\everything; \n"
+" //@ ensures \\result == 1; \n"
+" public int m3good(TestJava o) {\n"
+" o.i = 1;\n"
+" i = 2;\n"
+" return o.i;\n"
+" }\n"
+"}"
);
}
@Test
public void testLet() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" //@ ensures (\\let int k = i; \\result == k);\n"
+" public int m1(int i) {\n"
+" return i;\n"
+" }\n"
+" //@ ensures (\\let int k = 1; \\result == k);\n"
+" public int m1bad(int i) {\n"
+" return 2;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:9: warning: The prover cannot establish an assertion (Postcondition) in method m1bad",6
,"/tt/TestJava.java:7: warning: Associated declaration",7
);
}
@Test
public void testLet2() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" //@ ensures (\\let int k = i, int j = k; \\result == j);\n"
+" public int m1(int i) {\n"
+" return i;\n"
+" }\n"
+" //@ ensures (\\let int k = 1, int j = k; \\result == j);\n"
+" public int m1bad(int i) {\n"
+" return 2;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:9: warning: The prover cannot establish an assertion (Postcondition) in method m1bad",6
,"/tt/TestJava.java:7: warning: Associated declaration",7
);
}
// TODO - are these tests duplicated elsewhere?
@Test
public void testNullThrow1() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public void m1bad(int i) throws Exception {\n"
+" if (i == 0) \n"
+" throw null;\n"
+" }\n"
+" public void m2bad(int i, /*@ nullable */ Exception e) throws Exception {\n"
+" if (i == 0) \n"
+" throw e;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:5: warning: The prover cannot establish an assertion (PossiblyNullValue) in method m1bad",16
,"/tt/TestJava.java:9: warning: The prover cannot establish an assertion (PossiblyNullValue) in method m2bad",16
);
}
@Test
public void testNullThrow2() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" //@ requires i != 0; \n"
+" public void m1good(int i) throws Exception {\n"
+" if (i == 0) \n"
+" throw null;\n"
+" }\n"
+" //@ requires i != 0; \n"
+" public void m2good(int i, Exception e) throws Exception {\n"
+" if (i == 0) \n"
+" throw e;\n"
+" }\n"
+" public void m3good(int i, Exception e) throws Exception {\n"
+" if (i == 0) \n"
+" throw e;\n"
+" }\n"
+"}"
);
}
@Test public void testNullSynchronized1() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public void m1bad(/*@ nullable */ Object o) throws Exception {\n"
+" synchronized (o) {};\n"
+" }\n"
+" public void m2bad( Object o) throws Exception {\n"
+" synchronized (o) {\n"
+" o = null; };\n"
+" }\n"
+"}"
,"/tt/TestJava.java:4: warning: The prover cannot establish an assertion (PossiblyNullValue) in method m1bad",21
,"/tt/TestJava.java:8: warning: The prover cannot establish an assertion (PossiblyNullAssignment) in method m2bad",13
);
}
@Test public void testNullSynchronized2() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public void m1good(Object o) throws Exception {\n"
+" synchronized (o) {};\n"
+" }\n"
+" public void m2good(Object o) throws Exception {\n"
+" synchronized (this) {};\n"
+" }\n"
+"}"
);
}
// FIXME _ check that different return or throw statements are properly pointed to
// FIXME - need tests with multiple ensures and various cases
// FIXME - test definedness in postconditions
// FIXME - exceptional postconditions
// FIXME - need precondition checks for calling methods
// FIXME - need checks for ensures assumptions when calling methods
// FIXME - complete assignables
// FIXME - assignables for method calls
// FIXME - almost duplicat ewith escnew
@Test public void testArrayIndex() {
main.addOptions("-escMaxWarnings=1");
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public int f;\n"
+" //@ requires a.length == 10;\n"
+" public int m1bad(int[] a) {\n"
+" return a[10] ;\n"
+" }\n"
+" //@ requires a.length == 10;\n"
+" public int m1bada(int[] a) {\n"
+" return a[-1] ;\n"
+" }\n"
+" //@ requires a.length == 10 && i >= 0;\n"
+" public int m1badb(int[] a, int i) {\n"
+" return a[i] ;\n"
+" }\n"
+" //@ requires a.length == 10;\n"
+" public int m1good(int[] a) {\n"
+" return a[0] ;\n"
+" }\n"
+" //@ requires a.length == 10;\n"
+" public int m1gooda(int[] a) {\n"
+" return a[9] ;\n"
+" }\n"
+" //@ requires a.length == 10;\n"
+" //@ requires i >= 3;\n"
+" //@ requires i <= 8;\n"
+" public int m1goodb(int[] a, int i) {\n"
+" return a[i] ;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:6: warning: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method m1bad",13
,"/tt/TestJava.java:10: warning: The prover cannot establish an assertion (PossiblyNegativeIndex) in method m1bada",13
,"/tt/TestJava.java:14: warning: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method m1badb",13
);
}
@Test
public void testArrayIndex1() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public int f;\n"
+" //@ requires a.length == 10;\n"
+" public int m1bad(int[] a) {\n"
+" return a[10] ;\n"
+" }\n"
+" //@ requires a.length == 10;\n"
+" public int m1bada(int[] a) {\n"
+" return a[-1] ;\n"
+" }\n"
+" //@ requires i > 1 && a.length == 10;\n"
+" public int m1badb(int[] a, int i) {\n"
+" return a[i] ;\n"
+" }\n"
+" //@ requires i < 5 && a.length == 10;\n"
+" public int m1badc(int[] a, int i) {\n"
+" return a[i] ;\n"
+" }\n"
+" //@ requires a.length == 10;\n"
+" public int m1good(int[] a) {\n"
+" return a[0] ;\n"
+" }\n"
+" //@ requires a.length == 10;\n"
+" public int m1gooda(int[] a) {\n"
+" return a[9] ;\n"
+" }\n"
+" //@ requires a.length == 10;\n"
+" //@ requires i >= 3;\n"
+" //@ requires i <= 8;\n"
+" public int m1goodb(int[] a, int i) {\n"
+" return a[i] ;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:6: warning: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method m1bad",13
,"/tt/TestJava.java:10: warning: The prover cannot establish an assertion (PossiblyNegativeIndex) in method m1bada",13
,"/tt/TestJava.java:14: warning: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method m1badb",13
,"/tt/TestJava.java:18: warning: The prover cannot establish an assertion (PossiblyNegativeIndex) in method m1badc",13
);
}
@Test
public void testArrayValue() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public int f;\n"
+" //@ requires a.length == 10;\n"
+" //@ ensures \\result == a[1];\n"
+" public int m1bad(int[] a) {\n"
+" return a[0] ;\n"
+" }\n"
+" //@ requires a.length == 10;\n"
+" //@ ensures \\result == a[0];\n"
+" public int m1good(int[] a) {\n"
+" return a[0] ;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:7: warning: The prover cannot establish an assertion (Postcondition) in method m1bad",5
,"/tt/TestJava.java:5: warning: Associated declaration",7
);
}
@Test
public void testHavocB() {
main.addOptions("-method=m1");
helpTCX("tt.TestJava","package tt; \n"
+"/*@ nullable_by_default*/ public class TestJava { \n"
+" /*@ non_null */ public TestJava ooo;\n"
+" /*@ non_null */ public static TestJava sooo;\n"
+" public void m1(boolean b, /*@ non_null */ TestJava o) {\n"
+" ooo = o; sooo = o;\n"
+" if (b) meverything();\n"
+" //@ assert ooo != null;\n"
+" //@ assert ooo instanceof TestJava;\n"
+" }\n"
+" public void meverything() {\n"
+" }\n"
+"}"
);
}
@Test
public void testHavoc() {
main.addOptions("-method=m1","-show");
helpTCX("tt.TestJava","package tt; \n"
+"/*@ nullable_by_default*/ public class TestJava { \n"
+" /*@ non_null */ public TestJava ooo;\n"
+" /*@ non_null */ public static TestJava sooo;\n"
+" public void m1(boolean b, /*@ non_null */ TestJava o) {\n"
+" ooo = o; sooo = o;\n"
+" if (b) meverything();\n"
+" //@ assert ooo != null;\n"
+" //@ assert ooo instanceof TestJava;\n"
+" }\n"
+" //@ assignable ooo;\n"
+" public void meverything() {\n"
+" }\n"
+"}"
);
}
@Test
public void testAssignment() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public void m1bad(boolean i) {\n"
+" int x = 0 ;\n"
+" if (i) x = 1; else x = 2; ;\n"
+" x = x + 1 ;\n"
+" //@ assert x < 3 ;\n"
+" }\n"
+" public void m1ok(boolean i) {\n"
+" int x = 0 ;\n"
+" if (i) x = 1; else x = 2; ;\n"
+" x = x + 1 ;\n"
+" //@ assert x < 4 ;\n"
+" }\n"
+" public void m2ok(boolean i) {\n"
+" int x = 10 ;\n"
+" int y ;\n"
+" x = (y = x + 1) + 2 ;\n"
+" //@ assert x == 13 ;\n"
+" //@ assert y == 11 ;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:7: warning: The prover cannot establish an assertion (Assert) in method m1bad",9
);
}
@Test public void testAssignOp1() {
main.addOptions("-escMaxWarnings=1");
helpTCX("tt.TestJava","package tt; import org.jmlspecs.annotation.*; \n"
+"public class TestJava { \n"
+" public int f;\n"
+" //@ requires j < 1000 && -1000 < j; ensures \\result == j+j+1;\n"
+" public int m1good(int j) {\n"
+" int i = j ;\n"
+" return (i+=j+1) ;\n"
+" }\n"
+"}"
);
}
@Test public void testAssignOp1Div() {
Assume.assumeTrue(runLongTests);
Assume.assumeTrue(!"cvc4".equals(solver)); // SKIPPING because CVC4 does not handle integer division
main.addOptions("-escMaxWarnings=1");
main.addOptions("-logic=AUFNIRA");
helpTCX("tt.TestJava","package tt; import org.jmlspecs.annotation.*; \n"
+"public class TestJava { \n"
+" public int f;\n"
+" //@ requires j != 0;\n"
+" public int m2good(int j) {\n"
+" int i = j ;\n" // Line 20
+" return (i/=j) ;\n"
+" }\n"
+" //@ requires t != null;\n"
+" //@ requires i != 0;\n"
+" public void m3(TestJava t, int i) {\n"
+" t.f /= i ;\n"
+" }\n"
+" //@ requires t != null;\n"
+" //@ requires i != 0;\n"
+" //@ assignable \\everything;\n"
+" public void m3good(TestJava t, int i) {\n"
+" t.f /= i ;\n"
+" }\n"
+"}"
);
}
@Ignore // takes a long time
@Test public void testAssignOp2() {
main.addOptions("-escMaxWarnings=1");
main.addOptions("-logic=AUFNIRA");
helpTCX("tt.TestJava","package tt; import org.jmlspecs.annotation.*; \n"
+"public class TestJava { \n"
+" public int f;\n"
+" //@ ensures \\result == j;\n"
+" public int m1bad(int j) {\n"
+" int i = j ;\n"
+" return (i+=1) ;\n"
+" }\n"
+" public int m2bad(int j) {\n"
+" int i = j ;\n"
+" return (i/=j) ;\n"
+" }\n"
+" //@ assignable t.f;\n"
+" //@ requires t != null;\n"
+" public void m3badb(TestJava t, int i) {\n"
+" t.f /= i ;\n"
+" }\n"
+" //@ requires i != 0;\n"
+" //@ assignable \\everything;\n"
+" public void m3badc(@Nullable TestJava t, int i) {\n"
+" t.f /= i ;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:7: warning: The prover cannot establish an assertion (Postcondition) in method m1bad",5
,"/tt/TestJava.java:4: warning: Associated declaration",7
,"/tt/TestJava.java:11: warning: The prover cannot establish an assertion (PossiblyDivideByZero) in method m2bad",14
,"/tt/TestJava.java:16: warning: The prover cannot establish an assertion (PossiblyDivideByZero) in method m3badb",9
,"/tt/TestJava.java:21: warning: The prover cannot establish an assertion (PossiblyNullDeReference) in method m3badc",6
);
}
@Ignore // takes a long time
@Test public void testAssignOp3() {
main.addOptions("-escMaxWarnings=1");
main.addOptions("-logic=AUFNIRA");
helpTCX("tt.TestJava","package tt; import org.jmlspecs.annotation.*; \n"
+"public class TestJava { \n"
+" public int f;\n"
+" //@ requires i != 0;\n"
+" //@ assignable \\everything;\n"
+" public void m4bad(@Nullable int[] a, int i) {\n"
+" a[0] /= i ;\n"
+" }\n"
+" //@ requires a.length == 4;\n"
+" //@ requires i != 0;\n"
+" //@ assignable \\everything;\n"
+" public void m4badb(@NonNull int[] a, int i) {\n"
+" a[-1] /= i ;\n"
+" }\n"
+" //@ requires a.length == 4;\n"
+" //@ requires i != 0;\n"
+" //@ assignable \\everything;\n"
+" public void m4badc(@NonNull int[] a, int i) {\n"
+" a[4] /= i ;\n"
+" }\n"
+" //@ requires a.length == 4;\n"
+" //@ assignable \\everything;\n"
+" public void m4badd(@NonNull int[] a, int i) {\n"
+" a[0] /= i ;\n"
+" }\n"
+" //@ requires a.length == 4;\n"
+" //@ requires i != 0;\n"
+" //@ assignable \\everything;\n"
+" public void m4good(@NonNull int[] a, int i) {\n"
+" a[0] /= i ;\n"
+" }\n"
+" public void m10ok(boolean i) {\n"
+" int x = 10 ;\n"
+" int y = 20 ;\n"
+" x = (y += x + 1) + 2 ;\n"
+" //@ assert x == 33 ;\n"
+" //@ assert y == 31 ;\n"
+" }\n"
+"}"
,"/tt/TestJava.java:7: warning: The prover cannot establish an assertion (PossiblyNullDeReference) in method m4bad",-9
,"/tt/TestJava.java:7: warning: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method m4bad",-6
,"/tt/TestJava.java:7: warning: The prover cannot establish an assertion (PossiblyNullDeReference) in method m4bad",-6
,"/tt/TestJava.java:13: warning: The prover cannot establish an assertion (PossiblyNegativeIndex) in method m4badb",6
,"/tt/TestJava.java:19: warning: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method m4badc",6
,"/tt/TestJava.java:24: warning: The prover cannot establish an assertion (PossiblyDivideByZero) in method m4badd",10
);
}
@Test public void testArrays() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public void m1bad(/*@ nullable*/ int[] a, int i) {\n"
+" a[1] = 9;\n"
+" }\n"
+" //@ requires i < a.length; \n"
+" public void m2bad(int[] a, int i) {\n"
+" a[i] = 9;\n"
+" }\n"
+" //@ requires i >= 0; \n"
+" public void m3bad(int[] a, int i) {\n"
+" a[i] = 9;\n"
+" }\n"
+" //@ requires i >= 0 && i < a.length; \n"
+" public void m1good(int[] a, int i) {\n"
+" a[i] = 9;\n"
+" }\n"
+"}"
,anyorder(
seq("/tt/TestJava.java:4: warning: The prover cannot establish an assertion (PossiblyNullDeReference) in method m1bad",8),
seq("/tt/TestJava.java:4: warning: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method m1bad",8)
)
,"/tt/TestJava.java:8: warning: The prover cannot establish an assertion (PossiblyNegativeIndex) in method m2bad",8
,"/tt/TestJava.java:12: warning: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method m3bad",8
);
}
@Test public void testArrayType1() { // TODO: CVC4 takes 147 sec
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public void m1(int[] a) {\n"
+" //@ assume a != null && a.length > 1;\n"
+" a[0] = 9;\n"
+" }\n"
+" public void m2(Integer[] a, Integer i) {\n"
+" //@ assume a != null && a.length > 1 && i != null;\n"
+" Object[] o = a;\n"
+" o[0] = i;\n"
+" }\n"
+" public void m3(Integer[] a, Integer i) {\n"
+" //@ assume a != null && a.length > 1 && i != null;\n"
+" //@ assume \\elemtype(\\typeof(a)) == \\type(Integer);\n"
+" Object[] o = a;\n"
+" o[0] = i;\n"
+" }\n"
+" public void m4bad(Integer[] a, Object i) {\n"
+" //@ assume a != null && a.length > 1 && i != null;\n"
+" Object[] o = a;\n"
+" o[0] = i;\n"
+" }\n"
+" static class A {}\n"
+" static class B extends A {}\n"
+"}"
,"/tt/TestJava.java:21: warning: The prover cannot establish an assertion (PossiblyBadArrayAssignment) in method m4bad",12
);
}
@Test public void testArrayType1Bug() { // TODO: CVC4 takes 147 sec
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public void m1(int[] a) {\n"
+" //@ assume a != null && a.length > 1;\n"
+" a[0] = 9;\n"
+" }\n"
+" public void m2bad(String[] a, Integer i) {\n"
+" //@ assume a != null && a.length > 1 && i != null;\n"
+" Object[] o = a;\n"
+" o[0] = i;\n"
+" }\n"
+" public void m3(String[] a, String i) {\n"
+" //@ assume a != null && a.length > 1 && i != null;\n"
+" //@ assume \\elemtype(\\typeof(a)) == \\type(String);\n"
+" Object[] o = a;\n"
+" o[0] = i;\n"
+" }\n"
+" public void m4bad(String[] a, Object i) {\n"
+" //@ assume a != null && a.length > 1 && i != null;\n"
+" Object[] o = a;\n"
+" o[0] = i;\n"
+" }\n"
+" static class A {}\n"
+" static class B extends A {}\n"
+"}"
,"/tt/TestJava.java:10: warning: The prover cannot establish an assertion (PossiblyBadArrayAssignment) in method m2bad",12
,"/tt/TestJava.java:21: warning: The prover cannot establish an assertion (PossiblyBadArrayAssignment) in method m4bad",12
);
}
@Test public void testArrayType2() { // TODO: CVC4 takes 186 sec
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public void m3a(Integer[] a, Integer i) {\n"
+" //@ assume a != null && a.length > 1 && i != null;\n"
+" Object[] o = a;\n"
+" o[0] = i;\n"
+" }\n"
+" public void m5bad(A[] a, B i) {\n" // FAILS because 'a' might have a dynamic type that does not hold a B
+" //@ assume a != null && a.length > 1 && i != null;\n"
+" Object[] o = a;\n"
+" o[0] = i;\n"
+" }\n"
+" public void m5(A[] a, B i) {\n"
+" //@ assume a != null && a.length > 1 && i != null;\n"
+" //@ assume \\type(B) <: \\elemtype(\\typeof(a));\n"
+" Object[] o = a;\n"
+" o[0] = i;\n"
+" }\n"
+" static class A {}\n"
+" static class B extends A {}\n"
+"}"
,"/tt/TestJava.java:11: warning: The prover cannot establish an assertion (PossiblyBadArrayAssignment) in method m5bad",12
);
}
@Test public void testArrayType2Bug() { // TODO: CVC4 takes 186 sec
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public void m3a(String[] a, String i) {\n"
+" //@ assume a != null && a.length > 1 && i != null;\n"
+" Object[] o = a;\n"
+" o[0] = i;\n"
+" }\n"
+" static class A {}\n"
+" static class B extends A {}\n"
+"}"
);
}
@Test public void testMethodWithConstructorNameFixed() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public byte[] b;\n"
+" //@ public invariant b != null && b.length == 20;\n"
+" public TestJava(int i) {\n"
+" b = new byte[20];\n"
+" }\n"
+"}"
);
}
@Test public void testMultiException() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public void m() {}\n"
+" public void mm() {\n"
+" try {\n"
+" m();\n"
+" } catch (NullPointerException|ArithmeticException e) {\n"
+" //@ assert e instanceof NullPointerException || e instanceof ArithmeticException;\n"
+" }}\n"
+"}\n"
);
}
@Test public void testExceptionTypeC() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public void mm(int i) throws ClassNotFoundException, NoSuchMethodException {\n"
+" try {\n"
+" if (i == 0) throw new ClassNotFoundException();\n"
+" if (i == 1) throw new NoSuchMethodException();\n"
+" } catch (Exception e) {\n"
+" throw e;\n"
+" }}\n"
+"}\n"
);
}
@Test public void testExceptionType() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" //@ signals_only NullPointerException, ArithmeticException;\n"
+" public void mm(int i) throws NullPointerException, ArithmeticException {\n"
+" try {\n"
+" if (i == 0) throw new NullPointerException();\n"
+" if (i == 1) throw new ArithmeticException();\n"
+" } catch (Exception e) {\n"
+" throw e;\n"
+" }}\n"
+"}\n"
);
}
@Test public void testExceptionTypeB() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" //@ signals_only NullPointerException;\n"
+" public void mm(int i) throws NullPointerException {\n"
+" try {\n"
+" if (i == 0) throw new NullPointerException();\n"
+" if (i == 1) throw new ArithmeticException();\n"
+" } catch (Exception e) {\n"
+" throw e;\n"
+" }}\n"
+"}\n"
,"/tt/TestJava.java:9: warning: The prover cannot establish an assertion (ExceptionList) in method mm",6
,"/tt/TestJava.java:3: warning: Associated declaration",7
);
}
@Test public void testExceptionType2() {
expectedExit = 1;
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public void mm(int i) throws ClassNotFoundException {\n"
+" try {\n"
+" if (i == 0) throw new ClassNotFoundException();\n"
+" if (i == 1) throw new NoSuchMethodException();\n"
+" } catch (Exception e) {\n"
+" throw e;\n"
+" }}\n"
+"}\n"
,"/tt/TestJava.java:8: unreported exception java.lang.NoSuchMethodException; must be caught or declared to be thrown", 6
);
}
@Test public void testMethodWithConstructorNameOK() {
//main.addOptions("-verbose","-trace","-ce");
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public byte[] b;\n"
+" //@ public invariant b != null && b.length == 20;\n"
+" public TestJava(int i) {\n"
+" b = new byte[20];\n"
+" }\n"
// The following method - not constructor - note the return type
// appears to be legal Java
+" public void TestJava(int i) {\n"
+" b = new byte[20];\n"
+" }\n"
+"}"
);
}
@Test public void testMethodWithConstructorName() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public byte[] b;\n"
+" //@ public invariant b != null && b.length == 20;\n"
+" public TestJava() {\n"
+" }\n"
// The following method - not constructor - note the return type
// appears to be legal Java
+" public void TestJava(int i) {\n"
+" }\n"
+"}"
,"/tt/TestJava.java:5: warning: The prover cannot establish an assertion (InvariantExit) in method TestJava",10
,"/tt/TestJava.java:4: warning: Associated declaration",14
);
}
// Checks boxing conversion on assignment to a field
@Test public void testBoxingOnAssignment() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public int b;\n"
+" public Integer bb;\n"
+" public TestJava(Integer b, int bb) {\n"
+" this.b = b;\n"
+" this.bb = bb;\n"
+" }\n"
+"}"
);
}
@Test public void testMethodWithConstructorNameBug() {
main.addOptions("-no-internalSpecs");
// If there are no internal specs, then the implicit super() call of the
// Object() constructor may throw an exception. Then TestJava() would
// terminate exceptionally - and the invariant would not be established in
// that case either. With internal Specs, Object() is pure and has
// only normal termination.
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public byte[] b;\n"
+" //@ public invariant b != null && b.length == 20;\n"
+" public TestJava() {\n"
+" }\n"
+"}"
,anyorder(
seq("/tt/TestJava.java:5: warning: The prover cannot establish an assertion (InvariantExit) in method TestJava",10
,"/tt/TestJava.java:4: warning: Associated declaration",14)
,seq("/tt/TestJava.java:5: warning: The prover cannot establish an assertion (InvariantExceptionExit) in method TestJava",21
,"/tt/TestJava.java:4: warning: Associated declaration",14))
);
}
// A problem from MHuisman, with String initialization and invariants
@Test public void testStringInitialization() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public String x = new String();\n"
+" public TestJava(String xx) {\n"
+" this.x = xx;\n"
+" }\n"
+"}"
);
}
// If RR() throws an exception, mmm exits exceptionally
@Test public void testTryResources() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" static public int flag = 0;\n"
+" public static class RR implements AutoCloseable {\n"
+" //@ public normal_behavior\n"
+" //@ assignable TestJava.flag;\n"
+" //@ ensures TestJava.flag == 1;\n"
+" public void close() { TestJava.flag = 1; }\n"
+" }\n"
+" //@ requires flag == 0;\n"
+" //@ assignable flag;\n"
+" public void mmm() {\n"
+" //@ assert TestJava.flag == 0;\n"
+" try (RR r = new RR()){\n"
+" flag = 2; \n"
+" //@ assert TestJava.flag == 2;\n"
+" }\n"
+" //@ assert TestJava.flag == 1;\n"
+" }\n"
+"}"
);
}
// If RR() throws an exception, mmm exits exceptionally
// If close throws an exception, then mmm exits exceptionally and flag is not tested
@Test public void testTryResources1() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" static public int flag = 0;\n"
+" public static class RR implements AutoCloseable {\n"
+" //@ assignable TestJava.flag;\n"
+" //@ ensures TestJava.flag == 1;\n"
+" public void close() { TestJava.flag = 1; }\n"
+" }\n"
+" //@ requires flag == 0;\n"
+" //@ assignable flag;\n"
+" public void mmm() {\n"
+" //@ assert TestJava.flag == 0;\n"
+" try (RR r = new RR()){\n"
+" flag = 2; \n"
+" //@ assert TestJava.flag == 2;\n"
+" }\n"
+" //@ assert TestJava.flag == 1;\n"
+" }\n"
+"}"
);
}
// If RR() throws an exception, flag == 0
// If close exits normally, flag == 1
// If close throws an exception, flag == 10
@Test public void testTryResources1x() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" static public int flag = 0;\n"
+" public static class RR implements AutoCloseable {\n"
+" /*@ pure */ public RR(){}\n"
+" //@ assignable TestJava.flag;\n"
+" //@ ensures TestJava.flag == 1;\n"
+" //@ signals (Exception e) TestJava.flag == 10;\n"
+" public void close() { TestJava.flag = 1; }\n"
+" }\n"
+" //@ requires flag == 0;\n"
+" //@ assignable flag;\n"
+" public void mmm() {\n"
+" //@ assert TestJava.flag == 0;\n"
+" try {\n"
+" try (RR r = new RR()){\n"
+" flag = 2; \n"
+" //@ assert TestJava.flag == 2;\n"
+" }\n"
+" } catch (Exception eee) { \n"
+" //@ assert (\\lbl FLAG TestJava.flag) == 0 || TestJava.flag == 1|| TestJava.flag == 10;\n"
+" }\n"
+" }\n"
+"}"
);
}
// If RR() throws an exception, mmm exits exceptionally
@Test public void testTryResources1a() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" static public int flag = 0;\n"
+" public static class RR implements AutoCloseable {\n"
+" //@ assignable TestJava.flag;\n"
+" //@ ensures TestJava.flag == 1;\n"
+" //@ signals (Exception e) TestJava.flag == 1;\n"
+" public void close() { TestJava.flag = 1; }\n"
+" }\n"
+" //@ requires flag == 0;\n"
+" //@ assignable flag;\n"
+" public void mmm() {\n"
+" //@ assert TestJava.flag == 0;\n"
+" try (RR r = new RR()){\n"
+" flag = 2; \n"
+" //@ assert TestJava.flag == 2;\n"
+" }\n"
+" //@ assert TestJava.flag == 1;\n"
+" }\n"
+"}"
);
}
// Checks that close calls execute in reverse order
@Test public void testTryResources2() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" static public int flag = 0;\n"
+" public static class RR implements AutoCloseable {\n"
+" //@ public normal_behavior\n"
+" //@ assignable TestJava.flag;\n"
+" //@ ensures TestJava.flag == 1;\n"
+" public void close() { TestJava.flag = 1; }\n"
+" }\n"
+" public static class RR2 implements AutoCloseable {\n"
+" //@ public normal_behavior\n"
+" //@ assignable TestJava.flag;\n"
+" //@ ensures TestJava.flag == 2;\n"
+" public void close() { TestJava.flag = 2; }\n"
+" }\n"
+" //@ requires flag == 0;\n"
+" //@ assignable flag;\n"
+" public void mmm() {\n"
+" //@ assert TestJava.flag == 0;\n"
+" try (RR2 r = new RR2(); RR rr = new RR()){\n"
+" flag = 3; \n"
+" //@ assert TestJava.flag == 3;\n"
+" }\n"
+" //@ assert TestJava.flag == 2;\n"
+" }\n"
+"}"
);
}
// Checks the class of the resulting exception when try body and close calls throw exceptions
@Test public void testTryResources2b() {
// main.addOptions("-show","-progress","-method=mmm","-checkFeasibility=debug");
main.addOptions("-checkFeasibility=all");
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public static class EE extends Exception { /*@ public normal_behavior ensures true; */public EE() {}}\n"
+" public static class EE1 extends EE {/*@ public normal_behavior ensures true; */public EE1() {}}\n"
+" public static class EE2 extends EE {/*@ public normal_behavior ensures true; */public EE2() {}}\n"
+" public static class EE3 extends EE {/*@ public normal_behavior ensures true; */public EE3() {}}\n"
+" static public int flag = 0;\n"
+" public static class RR implements AutoCloseable {\n"
+" /*@ public normal_behavior ensures true; */ public RR() {}\n"
+" //@ public exceptional_behavior\n"
+" //@ assignable TestJava.flag;\n"
+" //@ signals_only EE1;\n"
+" //@ signals (Exception e) TestJava.flag == 1;\n"
+" public void close() throws EE { TestJava.flag = 1; throw new EE1(); }\n"
+" }\n"
+" public static class RR2 implements AutoCloseable {\n"
+" /*@ public normal_behavior ensures true; */ public RR2() {}\n"
+" //@ public exceptional_behavior\n"
+" //@ assignable TestJava.flag;\n"
+" //@ signals_only EE2;\n"
+" //@ signals (Exception e) TestJava.flag == 2;\n"
+" public void close() throws EE { TestJava.flag = 2; throw new EE2(); }\n"
+" }\n"
+" //@ requires flag == 0;\n"
+" //@ assignable flag;\n"
+" public void mmm() {\n" // Line 26
+" //@ assert TestJava.flag == 0;\n"
+" try {\n"
+" try (RR rr = new RR()){\n"
+" flag = 3; \n"
+" //@ assert TestJava.flag == 3;\n"
+" throw new EE3();\n"
+" }\n"
+" //@ assert TestJava.flag == 1;\n" // not feasible line 34
+" } catch (EE e) {\n"
+" //@ assert TestJava.flag == 1;\n"
+" //@ assert e instanceof EE3 ;\n" // Line 37
+" }\n"
+" }\n"
+"}"
,"/tt/TestJava.java:34: warning: There is no feasible path to program point before explicit assert statement in method tt.TestJava.mmm()",11
);
}
// Checks the class of the resulting exception when try body and close calls throw exceptions
@Test public void testTryResources2c() {
//main.addOptions("-show","-progress","-method=mmm","-checkFeasibility=debug");
main.addOptions("-checkFeasibility=all");
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public static class EE extends RuntimeException { /*@ public normal_behavior ensures true; */public EE() {}}\n"
+" public static class EE1 extends EE {/*@ public normal_behavior ensures true; */public EE1() {}}\n"
+" public static class EE2 extends EE {/*@ public normal_behavior ensures true; */public EE2() {}}\n"
+" public static class EE3 extends EE {/*@ public normal_behavior ensures true; */public EE3() {}}\n"
+" static public int flag = 0;\n"
+" public static class RR implements AutoCloseable {\n"
+" /*@ public normal_behavior ensures true; */ public RR() {}\n"
+" //@ public exceptional_behavior\n"
+" //@ assignable TestJava.flag;\n"
+" //@ signals_only EE1;\n"
+" //@ signals (Exception e) TestJava.flag == 1;\n"
+" public void close() { TestJava.flag = 1; throw new EE1(); }\n"
+" }\n"
+" public static class RR2 implements AutoCloseable {\n"
+" /*@ public normal_behavior ensures true; */ public RR2() {}\n"
+" //@ public exceptional_behavior\n"
+" //@ assignable TestJava.flag;\n"
+" //@ signals_only EE2;\n"
+" //@ signals (Exception e) TestJava.flag == 2;\n"
+" public void close() { TestJava.flag = 2; throw new EE2(); }\n"
+" }\n"
+" //@ requires flag == 0;\n"
+" //@ assignable flag;\n"
+" public void mmm() {\n" // Line 26
+" //@ assert TestJava.flag == 0;\n"
+" try {\n"
+" try (RR2 r = new RR2(); RR rr = new RR()){\n"
+" flag = 3; \n"
+" //@ assert TestJava.flag == 3;\n"
+" throw new EE3();\n"
+" }\n"
+" //@ assert TestJava.flag == 2;\n" // not feasible
+" } catch (EE1 | EE2 | EE3 e) {\n"
+" //@ assert e instanceof EE3 ;\n" // Line 36
+" }\n"
+" }\n"
+"}"
,"/tt/TestJava.java:34: warning: There is no feasible path to program point before explicit assert statement in method tt.TestJava.mmm()",11
);
}
// Checks the class of the resulting exception when close calls throw exceptions, but not the try body
@Test public void testTryResources2a() {
main.addOptions("-checkFeasibility=all");
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" public static class EE extends Exception { /*@ public normal_behavior ensures true; */public EE() {}}\n"
+" public static class EE1 extends EE {/*@ public normal_behavior ensures true; */public EE1() {}}\n"
+" public static class EE2 extends EE {/*@ public normal_behavior ensures true; */public EE2() {}}\n"
+" static public int flag = 0;\n"
+" public static class RR implements AutoCloseable {\n"
+" /*@ public normal_behavior ensures true; */ public RR() {}\n"
+" //@ public exceptional_behavior\n"
+" //@ assignable TestJava.flag;\n"
+" //@ signals_only EE1;\n"
+" //@ signals (Exception e) TestJava.flag == 1;\n"
+" public void close() throws EE1 { TestJava.flag = 1; throw new EE1(); }\n"
+" }\n"
+" public static class RR2 implements AutoCloseable {\n"
+" /*@ public normal_behavior ensures true; */ public RR2() {}\n"
+" //@ public exceptional_behavior\n"
+" //@ assignable TestJava.flag;\n"
+" //@ signals_only EE2;\n"
+" //@ signals (Exception e) TestJava.flag == 2;\n"
+" public void close() throws EE2 { TestJava.flag = 2; throw new EE2(); }\n"
+" }\n"
+" //@ requires flag == 0;\n" // Line 23
+" //@ assignable flag;\n"
+" public void mmm() throws EE {\n" // Line 25
+" //@ assert TestJava.flag == 0; \n"
+" try {\n"
+" try (RR2 r = new RR2(); RR rr = new RR()){\n"
+" flag = 3; \n"
+" //@ assert TestJava.flag == 3;\n"
+" }\n"
+" //@ assert TestJava.flag == 2;\n" // Not feasible
+" } catch (EE e) {\n"
+" //@ assert TestJava.flag == 2;\n" // Line 34 // SHould be OK
+" //@ assert e instanceof EE1;\n" // Line 35 // Should be OK
+" }\n"
+" }\n"
+"}"
,"/tt/TestJava.java:32: warning: There is no feasible path to program point before explicit assert statement in method tt.TestJava.mmm()",11
);
}
// Check that finally block of try encloses declarations and calls to close
@Test public void testTryResources3() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" static public int flag = 0;\n"
+" public static class RR implements AutoCloseable {\n"
+" //@ public normal_behavior\n"
+" //@ assignable TestJava.flag;\n"
+" //@ ensures TestJava.flag == 1;\n"
+" public void close() { TestJava.flag = 1; }\n"
+" }\n"
+" //@ requires flag == 0;\n"
+" //@ assignable flag;\n"
+" public void mmm() {\n"
+" //@ assert TestJava.flag == 0;\n"
+" try (RR rr = new RR()){\n"
+" flag = 3; \n"
+" //@ assert TestJava.flag == 3;\n"
+" } finally {\n"
+" flag = 2;"
+" }\n"
+" //@ assert TestJava.flag == 2;\n"
+" }\n"
+"}"
);
}
// If RR() throws an exception, then catch block will execute
@Test public void testTryResources4() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" static public int flag = 0;\n"
+" public static class RR implements AutoCloseable {\n"
+" //@ public normal_behavior\n"
+" //@ assignable TestJava.flag;\n"
+" //@ ensures TestJava.flag == 1;\n"
+" public void close() { TestJava.flag = 1; }\n"
+" }\n"
+" //@ requires flag == 0;\n"
+" //@ assignable flag;\n"
+" public void mmm() {\n"
+" boolean normal = true;\n"
+" //@ assert TestJava.flag == 0;\n"
+" try (RR rr = new RR()){\n"
+" flag = 3; \n"
+" //@ assert TestJava.flag == 3;\n"
+" } catch (Exception e) {\n"
+" flag = 2;"
+" normal = false;"
+" }\n"
+" //@ assert normal ==> flag == 1;\n"
+" //@ assert !normal ==> flag == 2;\n"
+" }\n"
+"}"
);
}
@Test public void testTryResources4a() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" static public int flag = 0;\n"
+" public static class RR implements AutoCloseable {\n"
+" //@ public normal_behavior\n"
+" //@ assignable TestJava.flag;\n"
+" //@ ensures TestJava.flag == 1;\n"
+" public void close() { TestJava.flag = 1; }\n"
+" }\n"
+" //@ requires flag == 0;\n"
+" //@ assignable flag;\n"
+" public void mmm() {\n"
+" //@ assert TestJava.flag == 0;\n"
+" try (RR rr = new RR()){\n"
+" flag = 3; \n"
+" //@ assert TestJava.flag == 3;\n"
+" throw new Exception();\n"
+" } catch (Exception e) {\n"
+" flag = 2;\n"
+" }\n"
+" //@ assert TestJava.flag == 2;\n" // FIXME - should not be able to skip the catch block
+" }\n"
+"}"
);
}
@Test public void testTryResources4b() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" static public int flag = 0;\n"
+" public static class RR implements AutoCloseable {\n"
+" //@ assignable TestJava.flag;\n"
+" //@ ensures TestJava.flag == 1;\n"
+" public void close() { TestJava.flag = 1; }\n"
+" }\n"
+" //@ requires flag == 0;\n"
+" //@ assignable flag;\n"
+" public void mmm() {\n"
+" //@ assert TestJava.flag == 0;\n"
+" try (RR rr = new RR()){\n"
+" flag = 3; \n"
+" //@ assert TestJava.flag == 3;\n"
+" throw new Exception();\n"
+" } catch (Exception e) {\n"
+" flag = 2;\n"
+" }\n"
+" //@ assert TestJava.flag == 2;\n" // FIXME - should not be able to skip the catch block
+" }\n"
+"}"
);
}
// No resource - executes the catch block
@Test public void testTryResources4c() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" static public int flag = 0;\n"
+" public static class RR implements AutoCloseable {\n"
+" //@ public normal_behavior\n"
+" //@ assignable TestJava.flag;\n"
+" //@ ensures TestJava.flag == 1;\n"
+" public void close() { TestJava.flag = 1; }\n"
+" }\n"
+" //@ requires flag == 0;\n"
+" //@ assignable flag;\n"
+" public void mmm() {\n"
+" //@ assert TestJava.flag == 0;\n"
+" try {\n"
+" flag = 3; \n"
+" //@ assert TestJava.flag == 3;\n"
+" throw new Exception();\n"
+" } catch (Exception e) {\n"
+" flag = 2;\n"
+" }\n"
+" //@ assert TestJava.flag == 2; \n"
+" }\n"
+"}"
);
}
// Checks that the outer finally block is last to execute
@Test public void testTryResources5() {
helpTCX("tt.TestJava","package tt; \n"
+"public class TestJava { \n"
+" static public int flag = 0;\n"
+" public static class RR implements AutoCloseable {\n"
+" //@ assignable TestJava.flag;\n"
+" //@ ensures TestJava.flag == 1;\n"
+" public void close() { TestJava.flag = 1; }\n"
+" }\n"
+" //@ requires flag == 0;\n"
+" //@ assignable flag;\n"
+" public void mmm() {\n"
+" //@ assert TestJava.flag == 0;\n"
+" try (RR rr = new RR()){\n"
+" flag = 3; \n"
+" //@ assert TestJava.flag == 3;\n"
+" } catch (Exception e) {\n"
+" flag = 2;"
+" } finally {\n"
+" flag = 5;"
+" }\n"
+" //@ assert TestJava.flag == 5;\n"
+" }\n"
+"}"
);
}
// FIXME - test all these try tests in a constructor
}