import checkers.igj.quals.*;
/**
*
* This is a test class for the IGJ Checker framework
*
* This class tests the basic operations, such as:
*
* <ul>
* <li> Mutation through references
* <li> Subtyping: Assignments, method invocations
* <li> Fields Rule (without any recursion)
* <li> method invocation rule (partially)
* </ul>
*
* This class does not test for {@code @AssignsFields} methods
*/
@Mutable
public class MutableClass {
int field = 5;
@Assignable int assignable = 4;
// Fields
@Mutable MutableClass mutableRef = new @Mutable MutableClass();
@ReadOnly MutableClass readOnlyRef = new @ReadOnly MutableClass();
public void mutableReassign() @Mutable {
// try to mutate
field = 3;
field += 2;
field++;
--field;
this.field++;
this.field = 3;
this.field += 2;
this.field++;
// reassigning an Assignable Field
assignable = 3;
assignable += 2;
assignable++;
--assignable;
this.assignable++;
this.assignable = 3;
this.assignable += 2;
this.assignable++;
mutableRef = null;
readOnlyRef = null;
}
public void roReassign() @ReadOnly {
// try to mutate
field = 3; // should emit error
field += 2; // should emit error
field++; // should emit error
--field; // should emit error
this.field++; // should emit error
this.field = 3; // should emit error
this.field += 2; // should emit error
this.field++; // should emit error
// reassigning an Assignable Field
assignable = 3;
assignable += 2;
assignable++;
--assignable;
this.assignable++;
this.assignable = 3;
this.assignable += 2;
this.assignable++;
mutableRef = null; // should emit error
readOnlyRef = null; // should emit error
}
// Method Calling
public void roMethodInvoke() @ReadOnly {
mutableReassign(); // should emit error
this.mutableReassign(); // should emit error
this.roReassign();
roReassign();
}
public void mutableRecieverInvoke() @Mutable {
mutableReassign();
this.mutableReassign();
this.roReassign();
roReassign();
}
public void mutateOther() @ReadOnly {
@Mutable MutableClass instance = new @Mutable MutableClass();
instance.mutableRecieverInvoke();
instance.mutableReassign();
instance.field = 5;
instance.assignable = 3;
instance.readOnlyRef.mutableReassign(); // should emit error
instance.readOnlyRef.assignable = 2;
}
public void mutateOetherRO() @Mutable {
@ReadOnly MutableClass instance = new @ReadOnly MutableClass();
instance.mutableRecieverInvoke(); //should emit error
instance.mutableReassign(); //should emit error
instance.field = 5; //should emit error
instance.assignable = 3;
instance.readOnlyRef.mutableReassign(); // should emit error
instance.mutableRef.field++;
instance.readOnlyRef.field++; // should emit error
}
}