JPredP 2 Runtime Precondition and Postcondition Checking in

  • Slides: 25
Download presentation
JPred-P 2: Runtime Precondition and Postcondition Checking in Java Josh Choi Mike Welch

JPred-P 2: Runtime Precondition and Postcondition Checking in Java Josh Choi Mike Welch

Precondition n … a fact that must always be true just prior to the

Precondition n … 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 n … a fact that must always be true just after the execution

Postcondition n … 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

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

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

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 ) { secure. Deposit( account,

How about… public void deposit( Account account, Money amount ) { secure. Deposit( account, amount ); assert( account != null ); }

How about… public void deposit( Account account, Money amount ) { secure. Deposit( account,

How about… public void deposit( Account account, Money amount ) { secure. Deposit( account, amount ); assert( account != null ); }

How about… public void deposit( Account account, Money amount ) ensures account != null

How about… public void deposit( Account account, Money amount ) ensures account != null { secure. Deposit( account, amount ); }

Get ready for this… public Person point. Of. No. Return( Person you ) requires

Get ready for this… public Person point. Of. No. Return( Person you ) requires you != null ensures ret$REF == null { System. out. println( you. get. Name() + “ goes away”); return null; }

JPred n Dynamic method dispatch based upon predicates public char what. Grade. Should. IGive(

JPred n Dynamic method dispatch based upon predicates public char what. Grade. Should. IGive( int test. Score when test. Score >= 90 { return ‘A’; } Public char what. Grade. Should. IGive( int test. Score ) when test. Score < 90 { return ‘F’; } )

JPred + Pre/Postconditions public void do. Term. Project( Student s ) requires s. has.

JPred + Pre/Postconditions public void do. Term. Project( Student s ) requires s. has. ALife == false ensures s. avg. Hours. Of. Sleep < 4 && s. finished. Project == false when p@Computer. Science. Grad. Student { /* do project */ } public void do. Term. Project( Student s ) { /* do project */ } = JPred-P 2

Implementation - Tools Used n Polyglot (Cornell) ¨ Compiler front end framework for building

Implementation - Tools Used n Polyglot (Cornell) ¨ Compiler front end framework for building Java language extensions n n CVC Lite (Stanford) ¨ Theorem prover n n Definition of new grammar Custom abstract syntax tree (AST) nodes Specialized AST traversal passes Predicate validation Multi. Java (http: //multijava. sourceforge. net) ¨ JPred written in Multi. Java

Implementation - Our Work n Added requires and ensures support on top of existing

Implementation - Our Work n 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: req. Node and ens. Node along with JPred’s when. Node (formerly called pred. Node) ¨

Implementation (continued) n Modified JPred’s traversal passes ¨ requires support n In the translator

Implementation (continued) n Modified JPred’s traversal passes ¨ requires support n 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) n ensures ¨ support Few issues involved n There can be multiple

Implementation (continued) n ensures ¨ support Few issues involved n There can be multiple method exit points: end of method body and arbitrary number of return statements ¨ n 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) n ensures support (continued) Locate all return statements in a method body

Implementation (continued) n ensures support (continued) Locate all return statements in a method body ¨ Enclose a return statement in an if-else statement ¨ n n Guards are the ensures predicate else body outputs postcondition failure message and terminates program

Implementation (continued) n ensures ¨ support (continued) Postcondition check on a return value requires

Implementation (continued) n ensures ¨ support (continued) Postcondition check on a return value requires a store n Ex: int f() ensures <? > ret$INT > 2 { … return int ret$INT 1+2; = 1+2; } if ( ret$INT > 2 ) return ret$INT; else /* postcondition failed */ }

Implementation (continued) n ensures ¨ support (continued) JPred’s predicates can have three types of

Implementation (continued) n ensures ¨ support (continued) JPred’s predicates can have three types of expressions: integer, boolean, and null n 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” n Object g() ensures ret$REF != null {…} ¨

Implementation (continued) n ensures ¨ support (continued) Define a new pass to be executed

Implementation (continued) n ensures ¨ support (continued) Define a new pass to be executed early Declare static ret$INT, ret$BOOL, and ret$REF variables in class body n When ensures predicate specifies any of those “keywords, ” they are valid variables in the AST and so Polyglot does not complain n

Example - Abstract Divide n returns the absolute value of the quotient of num

Example - Abstract Divide n returns the absolute value of the quotient of num divided by denom int abs. Divide( int num, int denom ) public static int abs. Divide( int num, int denom ) requires denom != 0 ensures ret$INT >= 0 when denom >= 0 { int result; if ( num > 0 ) result = num / denom; else result = -num / denom; return result; }

Example (continued) public static int abs. Divide( int num, int denom ) requires denom

Example (continued) public static int abs. Divide( int num, int denom ) requires denom != 0 ensures ret$INT >= 0 when denom < 0 { int result; if ( num > 0 ) result = -num / denom; else result = num / denom; return result; }

Example (continued) n Compiling the source code with JPred-P 2 produces a standard Java

Example (continued) n Compiling the source code with JPred-P 2 produces a standard Java translation public static int abs. Divide(int arg$0$Real, int arg$1$Real) { if (arg$1$Real < 0) return abs. Divide$body 1(arg$0$Real, arg$1$Real); else return abs. Divide$body 0(arg$0$Real, arg$1$Real); } Dispatch method

Example (continued) private static int abs. Divide$body 0(int num, int denom) { if (denom

Example (continued) private static int abs. Divide$body 0(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 n JPred-P 2 makes it easy on the programmer to enforce precondition and

Conclusion n JPred-P 2 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