jpred-p 2 : runtime precondition and postcondition checking in java
DESCRIPTION
JPred-P 2 : Runtime Precondition and Postcondition Checking in Java. Josh Choi Mike Welch. Precondition. … a fact that must always be true just prior to the execution of some section of code, such as when entering a procedure Can be enforced with assert() statements at top of procedure body - PowerPoint PPT PresentationTRANSCRIPT
JPred-P2: Runtime Precondition and Postcondition Checking in JavaJosh ChoiMike Welch
Precondition … a fact that must always be true just prior to the
execution of some section of code, such as when entering a procedure
Can be enforced with assert() statements at top of procedure body
In software engineering, usually specified simply as comments around a procedure body
Postcondition … a fact that must always be true just after the
execution of some section of code, such as when leaving a procedure
Could enforce with assert() statements at bottom of procedure body
Usually exists in the form of programmer comments
Wouldn’t it be nice if…
public int divide( int numr, int denr)
{
assert ( denr != 0 );
return numr / denr;
}
Wouldn’t it be nice if…
public int divide( int numr, int denr)
{
assert ( denr != 0 );
return numr / denr;
}
Wouldn’t it be nice if…
public int divide( int numr, int denr) requires denr != 0
{
return numr / denr;
}
How about…
public void deposit( Account account, Money amount )
{
secureDeposit( account, amount );
assert( account != null );
}
How about…
public void deposit( Account account, Money amount )
{
secureDeposit( account, amount );
assert( account != null );
}
How about…
public void deposit( Account account, Money amount ) ensures account != null
{
secureDeposit( account, amount );
}
Get ready for this…
public Person pointOfNoReturn( Person you )requires you != nullensures ret$REF == null
{System.out.println( you.getName() + “ goes away”);return null;
}
JPred Dynamic method dispatch based upon predicates
public char whatGradeShouldIGive( int testScore )when testScore >= 90
{return ‘A’;
}
Public char whatGradeShouldIGive( int testScore )when testScore < 90
{return ‘F’;
}
JPred + Pre/Postconditionspublic void doTermProject( Student s )
requires s.hasALife == falseensures s.avgHoursOfSleep < 4 &&
s.finishedProject == falsewhen p@ComputerScienceGradStudent
{/* do project */
}
public void doTermProject( Student s ){
/* do project */}
= JPred-P2
Implementation - Tools Used Polyglot (Cornell)
Compiler front end framework for building Java language extensions
Definition of new grammar Custom abstract syntax tree (AST) nodes Specialized AST traversal passes
CVC Lite (Stanford) Theorem prover
Predicate validation MultiJava (http://multijava.sourceforge.net)
JPred written in MultiJava
Implementation - Our Work Added requires and ensures support on top of
existing JPred Polyglot extension Modified JPred’s grammar definition files to support the
new optional keywords Added AST nodes: reqNode and ensNode along with
JPred’s whenNode (formerly called predNode)
Implementation (continued) Modified JPred’s traversal passes
requires support In the translator pass, add an if-else statement, with
the requires predicate as its guard Enclose the method body under the if’s body else body outputs precondition failure message and
terminates program
Implementation (continued) ensures support
Few issues involved There can be multiple method exit points: end of
method body and arbitrary number of return statements
Postcondition must be checked immediately before each of these exit points
How to specify postconditions on return values? Ex: int f() ensures <?> { …; return 1+2; }
Implementation (continued) ensures support (continued)
Locate all return statements in a method body Enclose a return statement in an if-else statement
Guards are the ensures predicate else body outputs postcondition failure message and
terminates program
Implementation (continued) ensures support (continued)
Postcondition check on a return value requires a store Ex:
int f() ensures <?>{
…return 1+2;
}
int f() ensures ret$INT > 2{
…int ret$INT = 1+2;if ( ret$INT > 2 )
return ret$INT;else
/* postcondition failed */}
Implementation (continued) ensures support (continued)
JPred’s predicates can have three types of expressions: integer, boolean, and null
Which means postcondition check on a return value is limited to one of those three types
Define ret$INT, ret$BOOL, and ret$REF “keywords” Ex: “Make sure g() returns a non-null reference”
Object g() ensures ret$REF != null {…}
Implementation (continued) ensures support (continued)
Define a new pass to be executed early Declare static ret$INT, ret$BOOL, and ret$REF
variables in class body When ensures predicate specifies any of those
“keywords,” they are valid variables in the AST and so Polyglot does not complain
Example - Abstract Divide int absDivide( int num, int denom ) returns the
absolute value of the quotient of num divided by denompublic static int absDivide( int num, int denom )
requires denom != 0ensures ret$INT >= 0when denom >= 0
{int result;
if ( num > 0 )result = num / denom;
elseresult = -num / denom;
return result;}
Example (continued)
public static int absDivide( int num, int denom )requires denom != 0ensures ret$INT >= 0when denom < 0
{int result;
if ( num > 0 )result = -num / denom;
elseresult = num / denom;
return result;}
Example (continued) Compiling the source code with JPred-P2 produces a
standard Java translation
public static int absDivide(int arg$0$Real, int arg$1$Real){
if (arg$1$Real < 0)return absDivide$body1(arg$0$Real, arg$1$Real);
elsereturn absDivide$body0(arg$0$Real, arg$1$Real);
}
Dispatch method
Example (continued)private static int absDivide$body0(int num, int denom) { if (denom != 0) {
int result;if (num > 0) result = num / denom;else result = -num / denom;ret$INT = result;if (ret$INT >= 0) return ret$INT;else {
System.out.println("postcondition failed: ret$INT >= 0");System.exit(1);return ret$INT;
} } else {
System.out.println("precondition failed: denom != 0");System.exit(1);return 0;
}}
Conclusion JPred-P2 makes it easy on the programmer to
enforce precondition and postcondition checking By defining these predicates in the method
header, code becomes a lot more readable Inheritance of requires and ensures clauses is an
idea for future work