package org.jmlspecs.openjmltest.testcases;
import java.util.ArrayList;
import java.util.Collection;
import org.jmlspecs.openjmltest.TCBase;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.ParameterizedWithNames;
import org.junit.runners.Parameterized.Parameters;
/** These tests check various improper declarations of model and ghost
* methods and fields.
* @author David R. Cok
*
*/
@RunWith(ParameterizedWithNames.class)
public class modelghost extends TCBase {
@Parameters
static public Collection<Boolean[]> parameters() {
Collection<Boolean[]> data = new ArrayList<>(2);
data.add(new Boolean[]{false});
data.add(new Boolean[]{true});
return data;
}
public modelghost(Boolean b) {
useSystemSpecs = b;
}
@Test
public void testClassSimple() {
helpTCF("A.java",
"public class A { /*@ model int m() { return B.n; } */ C mm() { return C.nn; }}\n" +
"/*@ model class B { public static int n; } */\n" +
"class C { public static C nn; }"
);
}
@Test
public void testClassSimple2() {
helpTCF("A.java",
"public class A { /*@ model int m() { return B.n; } */ B mm() { return B.nn; }}\n" +
"/*@ model class B { public static int n; } */\n"
,"/A.java:1: cannot find symbol\n symbol: class B\n location: class A",55
,"/A.java:1: cannot find symbol\n symbol: variable B\n location: class A",71
);
}
@Test
public void testClassSimple3() {
helpTCF("A.java",
"public class A { /*@ model B m() { return B.n; } */ }\n" +
"/*@ model class B { public static B n; } */\n"
);
}
@Test
public void testMethod() {
helpTCF("A.java",
"public class A { \n" +
" void m() {}\n" + // OK
" //@ model int m1() { return 0; }\n" + // OK
" /*@ model */ int m2() { return 9; }\n" + // BAD
" void p();\n" + // BAD
" //@ model int p1();\n" + // OK
" /*@ model */ int p2();\n" + // BAD
" //@ int q();\n" + // BAD
" static public class II {\n" + // Line 9
" void m() {}\n" + // OK
" //@ model int m1() { return 0; }\n" + // OK
" /*@ model */ int m2() { return 9; }\n" + // BAD
" void p();\n" + // BAD
" //@ model int p1();\n" + // OK
" /*@ model */ int p2();\n" + // BAD
" //@ int q();\n" + // BAD
" }\n" +
" /*@ static model public class III {\n" + // Line 18
" void m() {}\n" + // OK
" model int m1() { return 0; }\n" + // NO NESTING
" void p();\n" + // OK - FIXME - resolve the rules about model methods and embedded model declarations
" model int p1();\n" + // NO NESTING
" }*/\n" +
"}\n" +
"/*@ model class B { \n" + // Line 25
" void m() {}\n" + // OK
" model int m1() { return 0; }\n" + // NO NESTING
" void p();\n" + // OK -- FIXME - as above
" model int p1();\n" + // NO NESTING
"}\n*/" +
" class C { \n" + // Line 31
" void m() {}\n" + // OK
" //@ model int m1() { return 0; }\n" + // OK
" /*@ model */ int m2() { return 9; }\n" + // BAD
" void p();\n" + // BAD
" //@ model int p1();\n" + // OK
" /*@ model */ int p2();\n" + // BAD
" //@ int q();\n" + // BAD
"}"
// errors in a different order in Java 8
,"/A.java:4: A Java declaration (not within a JML annotation) may not be either ghost or model",20
,"/A.java:5: missing method body, or declare abstract",8
,"/A.java:7: missing method body, or declare abstract",20
,"/A.java:7: A Java declaration (not within a JML annotation) may not be either ghost or model",20
,"/A.java:8: A method or type declaration within a JML annotation must be model",11
,"/A.java:12: A Java declaration (not within a JML annotation) may not be either ghost or model",20
,"/A.java:13: missing method body, or declare abstract",8
,"/A.java:15: missing method body, or declare abstract",20
,"/A.java:15: A Java declaration (not within a JML annotation) may not be either ghost or model",20
,"/A.java:16: A method or type declaration within a JML annotation must be model",11
,"/A.java:20: A model type may not contain model declarations",13
//,"/A.java:21: missing method body, or declare abstract",8
//,"/A.java:22: missing method body, or declare abstract",13
,"/A.java:22: A model type may not contain model declarations",13
,"/A.java:27: A model type may not contain model declarations",14
//,"/A.java:28: missing method body, or declare abstract",8
//,"/A.java:29: missing method body, or declare abstract",14
,"/A.java:29: A model type may not contain model declarations",14
,"/A.java:34: A Java declaration (not within a JML annotation) may not be either ghost or model",20
,"/A.java:35: missing method body, or declare abstract",8
,"/A.java:37: missing method body, or declare abstract",20
,"/A.java:37: A Java declaration (not within a JML annotation) may not be either ghost or model",20
,"/A.java:38: A method or type declaration within a JML annotation must be model",11 // FIXME - beginning of declaration?
// ,"/A.java:8: A JML annotation must start with a JML keyword or have a Model or Ghost annotation: int",7
// ,"/A.java:16: A JML annotation must start with a JML keyword or have a Model or Ghost annotation: int",7
// ,"/A.java:38: A JML annotation must start with a JML keyword or have a Model or Ghost annotation: int",7
// ,"/A.java:4: A Java declaration (not within a JML annotation) may not be either ghost or model",20
// ,"/A.java:5: missing method body, or declare abstract",8
// ,"/A.java:7: missing method body, or declare abstract",20
// ,"/A.java:7: A Java declaration (not within a JML annotation) may not be either ghost or model",20
// ,"/A.java:12: A Java declaration (not within a JML annotation) may not be either ghost or model",20
// ,"/A.java:13: missing method body, or declare abstract",8
// ,"/A.java:15: missing method body, or declare abstract",20
// ,"/A.java:15: A Java declaration (not within a JML annotation) may not be either ghost or model",20
// ,"/A.java:20: A model type may not contain model declarations",13
// ,"/A.java:21: missing method body, or declare abstract",8
// ,"/A.java:22: missing method body, or declare abstract",13
// ,"/A.java:22: A model type may not contain model declarations",13
// ,"/A.java:34: A Java declaration (not within a JML annotation) may not be either ghost or model",20
// ,"/A.java:35: missing method body, or declare abstract",8
// ,"/A.java:37: missing method body, or declare abstract",20
// ,"/A.java:37: A Java declaration (not within a JML annotation) may not be either ghost or model",20
// ,"/A.java:27: A model type may not contain model declarations",14
// ,"/A.java:28: missing method body, or declare abstract",8
// ,"/A.java:29: missing method body, or declare abstract",14
// ,"/A.java:29: A model type may not contain model declarations",14
);
}
@Test
public void testUseMethod() {
helpTCF("A.java",
"public class A { \n" +
" boolean m() {}\n" + // OK
" //@ model boolean m1() { return true; }\n" + // OK
" //@ invariant m() && m1();\n" +
" //@ requires m() && m1();\n" +
" void p() {} ;\n" +
" //@ requires m() && m1();\n" + // BAD - VISIBILITY PROBLEMS
" public void pp() {} ;\n" +
"}\n"
,"/A.java:7: An identifier with package visibility may not be used in a requires clause with public visibility",16
,"/A.java:7: An identifier with package visibility may not be used in a requires clause with public visibility",23
);
}
@Test
public void testUseMethod2() {
helpTCF("A.java",
"public class A { \n" +
" //@ requires B.m() && B.m1();\n" +
" static void p() {};\n" +
" //@ requires B.m() && B.m1();\n" + // BAD - VISIBILITY PROBLEMS
" public static void pp() {} ;\n" +
"}\n" +
"class B { \n" +
" static boolean m() {}\n" + // OK
" //@ model static boolean m1() { return true; }\n" + // OK
" //@ static invariant m() && m1();\n" +
"}\n"
,"/A.java:4: An identifier with package visibility may not be used in a requires clause with public visibility",17
,"/A.java:4: An identifier with package visibility may not be used in a requires clause with public visibility",26
);
}
@Test
public void testUseJML() {
if (!useSystemSpecs) return; // Irrelevant if useSystemSpecs is false
helpTCF("A.java",
"import org.jmlspecs.lang.JML; public class A { \n" +
" //@ requires JML.erasure(\\typeof(this)) == JML.erasure(\\type(A));\n" +
" void p() {};\n" +
"}\n"
);
}
@Test
public void testClass() {
helpTCF("A.java",
"public class A { \n" +
" //@ model static public class B{}\n" +
" /*@ model */ static public class C{}\n" + // NOT MODEL
" //@ static public class D{}\n" + // SHOULD BE MODEL
" public class AA { \n" +
" //@ model public class B{}\n" +
" /*@ model */ public class C{}\n" + // NOT MODEL
" //@ public class D{}\n" + // SHOULD BE MODEL
" }\n" +
" /*@ model public class M { \n" + // Line 10
" model public class B{}\n" + // NO POINT
" public class C{}\n" +
" }*/\n" +
"}\n" +
"/*@ model */ class Y { \n" + // BAD
"}\n" +
"/*@ model class Q { \n" +
" model public class C{}\n" + // NO POINT
" public class D{}\n" +
"}*/\n" + // Line 20
"class Z { \n" +
" //@ model public class B{}\n" +
" /*@ model */ public class C{}\n" + // BAD
" //@ public class D{}\n" + // BAD
"}\n"
// Java 8
,"/A.java:3: A Java declaration (not within a JML annotation) may not be either ghost or model",30
,"/A.java:4: A method or type declaration within a JML annotation must be model", 21
,"/A.java:7: A Java declaration (not within a JML annotation) may not be either ghost or model",26
,"/A.java:8: A method or type declaration within a JML annotation must be model", 17
,"/A.java:11: A model type may not contain model declarations",19
,"/A.java:15: A Java declaration (not within a JML annotation) may not be either ghost or model",14
,"/A.java:18: A model type may not contain model declarations",17
,"/A.java:23: A Java declaration (not within a JML annotation) may not be either ghost or model",24
,"/A.java:24: A method or type declaration within a JML annotation must be model", 15
// Java 7
// ,"/A.java:4: A JML annotation must start with a JML keyword or have a Model or Ghost annotation: class",21
// ,"/A.java:8: A JML annotation must start with a JML keyword or have a Model or Ghost annotation: class",17
// ,"/A.java:24: A JML annotation must start with a JML keyword or have a Model or Ghost annotation: class",15
// ,"/A.java:3: A Java declaration (not within a JML annotation) may not be either ghost or model",30
// ,"/A.java:7: A Java declaration (not within a JML annotation) may not be either ghost or model",26
// ,"/A.java:11: A model type may not contain model declarations",19
// ,"/A.java:15: A Java declaration (not within a JML annotation) may not be either ghost or model",14
// ,"/A.java:23: A Java declaration (not within a JML annotation) may not be either ghost or model",24
// ,"/A.java:18: A model type may not contain model declarations",17
);
}
@Test
public void testField() {
helpTCF("A.java",
"public class A { \n" +
" int m;\n" + // OK
" //@ model int m1;\n" + // OK
" //@ ghost int m1a;\n" + // OK
" /*@ model */ int m2;\n" + // BAD
" /*@ ghost */ int m2a;\n" + // BAD
" //@ int q;\n" + // BAD
" static public class II {\n" + // Line 8
" int m;\n" + // OK
" //@ model int m1;\n" + // OK
" //@ ghost int m1a;\n" + // OK
" /*@ model */ int m2;\n" + // BAD
" /*@ ghost */ int m2a;\n" + // BAD
" //@ int q;\n" + // BAD
" }\n" +
" /*@ static model public class III {\n" + // Line 16
" int m;\n" + // OK
" model int m1;\n" + // NO NESTING
" ghost int m1a;\n" + // NO NESTING
" \n" +
" }*/\n" +
"}\n" +
"/*@ model class B { \n" + // Line 23
" int m;\n" + // OK
" model int m1; ghost int m2; \n" + // NO NESTING
"}\n*/" +
" class C { \n" + // Line 31
" int m;\n" + // OK
" //@ model int m1;\n" + // OK
" //@ ghost int m1a;\n" + // OK
" /*@ model */ int m2;\n" + // BAD
" /*@ ghost */ int m2a;\n" + // BAD
" //@ int q;\n" + // BAD
"}"
// Order changed for Java8
,"/A.java:5: A Java declaration (not within a JML annotation) may not be either ghost or model",20
,"/A.java:6: A Java declaration (not within a JML annotation) may not be either ghost or model",20
,"/A.java:7: A declaration within a JML annotation must be either ghost or model",11
,"/A.java:12: A Java declaration (not within a JML annotation) may not be either ghost or model",20
,"/A.java:13: A Java declaration (not within a JML annotation) may not be either ghost or model",20
,"/A.java:14: A declaration within a JML annotation must be either ghost or model",11
,"/A.java:18: A model type may not contain model declarations",15
,"/A.java:19: A model type may not contain ghost declarations",15
,"/A.java:25: A model type may not contain model declarations",14
,"/A.java:25: A model type may not contain ghost declarations",28
,"/A.java:31: A Java declaration (not within a JML annotation) may not be either ghost or model",20
,"/A.java:32: A Java declaration (not within a JML annotation) may not be either ghost or model",20
,"/A.java:33: A declaration within a JML annotation must be either ghost or model",11 // FIXME - beginning of declaration?
// ,"/A.java:7: A JML annotation must start with a JML keyword or have a Model or Ghost annotation: int",7
// ,"/A.java:14: A JML annotation must start with a JML keyword or have a Model or Ghost annotation: int",7
// ,"/A.java:33: A JML annotation must start with a JML keyword or have a Model or Ghost annotation: int",7
// ,"/A.java:5: A Java declaration (not within a JML annotation) may not be either ghost or model",20
// ,"/A.java:6: A Java declaration (not within a JML annotation) may not be either ghost or model",20
// ,"/A.java:12: A Java declaration (not within a JML annotation) may not be either ghost or model",20
// ,"/A.java:13: A Java declaration (not within a JML annotation) may not be either ghost or model",20
// ,"/A.java:18: A model type may not contain model declarations",15
// ,"/A.java:19: A model type may not contain ghost declarations",15
// ,"/A.java:31: A Java declaration (not within a JML annotation) may not be either ghost or model",20
// ,"/A.java:32: A Java declaration (not within a JML annotation) may not be either ghost or model",20
// ,"/A.java:25: A model type may not contain model declarations",14
// ,"/A.java:25: A model type may not contain ghost declarations",28
);
}
@Test
public void testInitializer() {
addMockFile("$A/A.jml","public class A { { i = 2; } }");
helpTCF("A.java","public class A { int i; { i = 1; } } "
,"/$A/A.jml:1: Initializer blocks are not allowed in specifications",18
);
}
@Test
public void testInitializer2() {
addMockFile("$A/A.jml","public class A { } /*@ model class B { int i; { i = 2; } } */ ");
helpTCF("A.java","public class A { int i; { i = 1; } } "
);
}
@Test
public void testInitializer2a() {
addMockFile("$A/A.jml","public class A { } /*@ model public class B { int i; { i = 2; } } */ ");
helpTCF("A.java","public class A { int i; { i = 1; } } "
,"/A.java:1: class B is public, should be declared in a file named B.java",37
);
}
@Test
public void testPackage() {
addMockFile("$A/A.jml","package p; public class A { /*@ model public class B { int i; { i = 2; } } */ }");
helpTCF("A.java","package p; public class A { int i; { i = 1; } } "
);
}
@Test
public void testPackage2() {
addMockFile("$A/A.jml","package pp; public class A { /*@ model public class B { int i; { i = 2; } } */ }");
helpTCF("A.java","package p; public class A { int i; { i = 1; } } "
);
}
@Test public void testInterface() {
helpTCF("TestJava.java","package tt; \n"
+"public interface TestJava { \n"
+" //@ public model int z;\n"
+" //@ static model int z2;\n"
+" public static int zz = 0;\n"
+"}"
);
}
}