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 racnew3 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; } /** Tests not_modified */ @Test public void testNotModified1() { helpTCX("tt.TestJava","package tt; import org.jmlspecs.annotation.*; \n" + "public class TestJava { \n" + " public static void main(String... args) {\n" + " m(3);\n" + " }" + " public static void m(int i) {\n" + " i = 3;\n" + " //@ assert \\not_modified(i);\n" + " i = 4;\n" + " //@ assert \\not_modified(i);\n" + // FAILS " }" + "}" ,"/tt/TestJava.java:9: JML assertion is false" ); } /** Tests not_modified */ @Test public void testNotModified2() { helpTCX("tt.TestJava","package tt; import org.jmlspecs.annotation.*; \n" + "public class TestJava { \n" + " int f = 5;\n" + " public static void main(String... args) {\n" + " (new TestJava()).m(3,2);\n" + " }" + " public void m(int i, int j) {\n" + " i = 4;\n" + " //@ assert \\not_modified(j,this.f,f);\n" + " f=6;\n" + " //@ assert \\not_modified(this.f);\n" + // FAILS " }" + "}" ,"/tt/TestJava.java:10: JML assertion is false" ); } /** Tests not_modified */ @Test public void testNotModified3() { helpTCX("tt.TestJava","package tt; import org.jmlspecs.annotation.*; \n" + "public class TestJava { \n" + " int f = 5;\n" + " public static void main(String... args) {\n" + " (new TestJava()).m(3,2);\n" + " }" + " public void m(int i, int j) {\n" + " i = 4;\n" + " //@ assert \\not_modified(j,this.f,f);\n" + " f=6;\n" + " //@ assert \\not_modified(f);\n" + // FAILS " }" + "}" ,"/tt/TestJava.java:10: JML assertion is false" ); } /** Tests not_modified */ @Test public void testNotModified4() { helpTCX("tt.TestJava","package tt; import org.jmlspecs.annotation.*; \n" + "public class TestJava { \n" + " int f = 5;\n" + " public static void main(String... args) {\n" + " (new TestJava()).m(new int[]{1,2},7);\n" + " }" + " public void m(int[] a, int j) {\n" + " j = 4;\n" + " //@ assert \\not_modified(a[0]);\n" + " a[0]=10;\n" + " //@ assert \\not_modified(a[0]);\n" + // FAILS " }" + "}" ,"/tt/TestJava.java:10: JML assertion is false" ); } // FIXME - need tests for X.f X.* o.* a[*] a[1..3] a[1..] @Test public void testCast() { helpTCX("tt.TestJava","package tt; \n" +"public class TestJava { \n" +" public static double d;\n" +" public static float f;\n" +" public static long l;\n" +" public static int i;\n" +" public static short s;\n" +" public static char c;\n" +" public static byte b;\n" +" public static void main(String... args) {\n" +" i = 6; m0(); \n" +" i = 100000; m0bad(); \n" +" }\n" +" //@ requires i == 6;\n" +" //@ modifies \\everything;\n" +" public static void m0() {\n" +" s = (short)i;\n" +" //@ assert s == i;\n" // OK +" b = (byte)i;\n" +" //@ assert b == i;\n" // OK // Line 20 +" c = (char)i;\n" +" //@ assert c == i;\n" // OK +" l = (long)i;\n" +" //@ assert l == i;\n" // OK +" int ii = (int)i;\n" +" //@ assert ii == i;\n" // OK +" //@ assert i == (short)i;\n" +" //@ assert i == (long)i;\n" +" //@ assert i == (char)i;\n" +" //@ assert i == (byte)i;\n" +" //@ assert i == (int)i;\n" +" }\n" +" //@ requires i == 100000;\n" +" //@ modifies \\everything;\n" +" public static void m0bad() {\n" +" s = (short)i;\n" +" //@ assert s == i;\n" // BAD // Line 37 +" b = (byte)i;\n" +" //@ assert b == i;\n" // BAD +" c = (char)i;\n" +" //@ assert c == i;\n" // BAD +" l = (long)i;\n" +" //@ assert l == i;\n" // OK +" int ii = (int)i;\n" +" //@ assert ii == i;\n" // OK +" //@ assert i == (short)i;\n" // BAD // Line +" //@ assert i == (long)i;\n" +" //@ assert i == (char)i;\n" +" //@ assert i == (byte)i;\n" +" //@ assert i == (int)i;\n" +" }\n" +"}" ,"/tt/TestJava.java:36: JML argument to numeric cast is out of range of the target type" ,"/tt/TestJava.java:37: JML assertion is false" ,"/tt/TestJava.java:38: JML argument to numeric cast is out of range of the target type" ,"/tt/TestJava.java:39: JML assertion is false" ,"/tt/TestJava.java:40: JML argument to numeric cast is out of range of the target type" ,"/tt/TestJava.java:41: JML assertion is false" ,"/tt/TestJava.java:46: JML argument to numeric cast is out of range of the target type" ,"/tt/TestJava.java:46: JML assertion is false" ,"/tt/TestJava.java:48: JML argument to numeric cast is out of range of the target type" ,"/tt/TestJava.java:48: JML assertion is false" ,"/tt/TestJava.java:49: JML argument to numeric cast is out of range of the target type" ,"/tt/TestJava.java:49: JML assertion is false" ); } @Test public void testCast1() { //main.addOptions("-show","-method=m0"); helpTCX("tt.TestJava","package tt; \n" +"public class TestJava { \n" +" public static void main(String... args) {\n" +" m0(); \n" +" }\n" +" public static void m0() {\n" +" {/*@ nullable */ Short s = null;\n" +" try { //@ assert 0 == (short)s; \n} catch (NullPointerException e) {}\n" +" try { short d = (Short)null; \n} catch (NullPointerException e) {}\n" // Lines 10-11 +" }\n" +" {/*@ nullable */ Long s = null;\n" +" try { //@ assert 0 == (long)s;\n} catch (NullPointerException e) {}\n" +" try { long d = (Long)null;\n} catch (NullPointerException e) {}\n" +" }\n" +" {/*@ nullable */ Byte s = null;\n" +" try { //@ assert 0 == (byte)s;\n} catch (NullPointerException e) {}\n" +" try { byte d = (Byte)null;\n} catch (NullPointerException e) {}\n" +" }\n" +" {/*@ nullable */ Integer s = null;\n" +" try { //@ assert 0 == (int)s;\n} catch (NullPointerException e) {}\n" +" try { int d = (Integer)null;\n} catch (NullPointerException e) {}\n" +" }\n" +" {/*@ nullable */ Character s = null;\n" +" try { //@ assert 0 == (char)s;\n} catch (NullPointerException e) {}\n" +" try { char d = (Character)null;\n} catch (NullPointerException e) {}\n" +" }\n" +" {/*@ nullable */ Float s = null;\n" +" try { //@ assert 0 == (float)s;\n} catch (NullPointerException e) {}\n" +" try { float d = (Float)null;}\n catch (NullPointerException e) {}\n" +" }\n" +" {/*@ nullable */ Double s = null;\n" +" try { //@ assert 0 == (double)s;\n} catch (NullPointerException e) {}\n" +" try { double d = (Double)null;\n} catch (NullPointerException e) {}\n" +" }\n" +" {/*@ nullable */ Boolean s = null;\n" +" try { //@ assert (boolean)s;\n} catch (NullPointerException e) {}\n" +" try { boolean d = (Boolean)null;\n} catch (NullPointerException e) {}\n" +" }\n" +" }\n" +"}" ,"/tt/TestJava.java:8: JML Attempt to unbox a null object within a JML expression" ,"/tt/TestJava.java:10: JML Attempt to unbox a null object" ,"/tt/TestJava.java:14: JML Attempt to unbox a null object within a JML expression" ,"/tt/TestJava.java:16: JML Attempt to unbox a null object" ,"/tt/TestJava.java:20: JML Attempt to unbox a null object within a JML expression" ,"/tt/TestJava.java:22: JML Attempt to unbox a null object" ,"/tt/TestJava.java:26: JML Attempt to unbox a null object within a JML expression" ,"/tt/TestJava.java:28: JML Attempt to unbox a null object" ,"/tt/TestJava.java:32: JML Attempt to unbox a null object within a JML expression" ,"/tt/TestJava.java:34: JML Attempt to unbox a null object" ,"/tt/TestJava.java:38: JML Attempt to unbox a null object within a JML expression" ,"/tt/TestJava.java:40: JML Attempt to unbox a null object" ,"/tt/TestJava.java:44: JML Attempt to unbox a null object within a JML expression" ,"/tt/TestJava.java:46: JML Attempt to unbox a null object" ,"/tt/TestJava.java:50: JML Attempt to unbox a null object within a JML expression" ,"/tt/TestJava.java:52: JML Attempt to unbox a null object" ); } @Test public void testCast2() { helpTCX("tt.TestJava","package tt; \n" +"public class TestJava { \n" +" public static void main(String... args) {\n" +" m1(); \n" +" }\n" +" public static void m1() {\n" +" short s = (short)9;\n" +" //@ assert 9 == (Short)s;\n" +" }\n" +"}" ); } @Test public void testVarargs() { helpTCX("tt.TestJava","package tt; \n" +"public class TestJava { \n" +" public static void main(String... args) {\n" +" m1(args); \n" +" m1(); \n" +" m1(\"a\"); \n" +" m1(\"a\",\"b\"); \n" +" }\n" +" //@ requires args.length >= 0; \n" +" //@ ensures args.length == \\result; \n" +" public static int m1(String ... args) {\n" +" return args.length;\n" +" }\n" +"}" ); } @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 static 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" +" public static void main(String ... args) {\n" +" mmm();\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 static 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" +" public static void main(String ... args) {\n" +" mmm();\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 static 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" +" //@ assert TestJava.flag == 100;\n" // ERROR - line 19 +" }\n" +" public static void main(String ... args) {\n" +" mmm();\n" +" }\n" +"}" ,"/tt/TestJava.java:19: JML assertion is false" ); } // Checks that close calls execute in reverse order @Test public void testTryResources2() { main.addOptions("-racCheckAssumptions"); 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 static 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" +" //@ assert TestJava.flag == 200;\n" // ERROR - line 25 +" }\n" +" public static void main(String ... args) {\n" +" mmm();\n" +" }\n" +"}" ,"/tt/TestJava.java:25: JML assertion is false" ); } // Checks the class of the resulting exception when try body and close calls throw exceptions @Test public void testTryResources2b() { main.addOptions("-racCheckAssumptions"); 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 static 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 == 111;\n" // not feasible - so not checked in RAC +" } catch (EE e) {\n" +" //@ assert TestJava.flag == 1;\n" +" //@ assert e instanceof EE3 ;\n" // Line 37 +" //@ assert TestJava.flag == 100;\n" +" }\n" +" }\n" +" public static void main(String ... args) {\n" +" mmm();\n" +" }\n" +"}" ,"/tt/TestJava.java:38: JML assertion is false" ); } // Checks the class of the resulting exception when try body and close calls throw exceptions @Test public void testTryResources2c() { main.addOptions("-racCheckAssumptions"); 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 static 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 == 222;\n" // not feasible - so not checked in RAC +" } catch (EE1 | EE2 | EE3 e) {\n" +" //@ assert e instanceof EE3 ;\n" // Line 36 +" //@ assert flag == 2;\n" +" //@ assert flag == 100;\n" // Error +" }\n" +" }\n" +" public static void main(String ... args) {\n" +" mmm();\n" +" }\n" +"}" ,"/tt/TestJava.java:38: JML assertion is false" ); } // Checks the class of the resulting exception when close calls throw exceptions, but not the try body @Test public void testTryResources2a() { main.addOptions("-show"); 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 static void mmm() {\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 == 222;\n" // Not feasible - so not checked in RAC +" } 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" +" public static void main(String ... args) {\n" +" mmm();\n" +" }\n" +"}" ); } // 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 static 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" +" public static void main(String ... args) {\n" +" mmm();\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 static 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" +" public static void main(String ... args) {\n" +" mmm();\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 static 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" +" public static void main(String ... args) {\n" +" mmm();\n" +" }\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 static 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" +" public static void main(String ... args) {\n" +" mmm();\n" +" }\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 static 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" +" public static void main(String ... args) {\n" +" mmm();\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 static 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" +" public static void main(String ... args) {\n" +" mmm();\n" +" }\n" +"}" ); } }