The Java Assertion Assertion A Java statement in

  • Slides: 28
Download presentation
The Java Assertion

The Java Assertion

Assertion • A Java statement in JDK 1. 4 & newer • Intent: enables

Assertion • A Java statement in JDK 1. 4 & newer • Intent: enables code to test assumptions. E. g. , a method that calculates the a particle’s speed, asserts: speed < c (speed of light). • Has a boolean expression whose value is “asserted” to be true when the assertion executes. – If it is false, the system throws an error. – By evaluating the boolean expression, the assertion confirms assumptions about program behavior. Increases confidence that the program is error-free. 2

Assertion … • Assert: Detecting bugs is quicker when assertions are included in the

Assertion … • Assert: Detecting bugs is quicker when assertions are included in the code. • Assertions also document the program, enhancing maintainability. 3

Outline • Introduction • Using Assertions • Compiling Files That Use Assertions • Enabling

Outline • Introduction • Using Assertions • Compiling Files That Use Assertions • Enabling & Disabling Assertions 4

Introduction • The assertion statement has 2 forms: assert Expression; // Expression 1 is

Introduction • The assertion statement has 2 forms: assert Expression; // Expression 1 is boolean Meaning: if ( ! Expression ) { throw Assertion. Error // no message } 5

Introduction … assert Expression 1 : Expression 2 ; where: – Expression 1 is

Introduction … assert Expression 1 : Expression 2 ; where: – Expression 1 is boolean – Expression 2 has a value Cannot be the returned value of a void method. Meaning: if ( ! Expression 1 ) { throw new Assertion. Error( Expression 2 ) } // Expression 2’s String value is the message. 6

The Message • Should convey details of the assertion failure • Is not a

The Message • Should convey details of the assertion failure • Is not a user-level message • Need not be understandable in isolation • Is intended for use with: – a full stack trace – the source code. 7

Introduction … • The stack trace gives the file/line# of the failed assertion. •

Introduction … • The stack trace gives the file/line# of the failed assertion. • Use the message form only to add information that helps diagnose the failure. E. g. , if Expression 1 involves a relationship between variables x & y, use the message form. E. g. , assert x < y : “x: “ + x + “, y: “ + y ; 8

Introduction … • Assertions can be enabled or disabled when the program is started.

Introduction … • Assertions can be enabled or disabled when the program is started. • Assertions are disabled by default. • Disabled assertions are equivalent to empty statements in semantics & performance. 9

Outline • Introduction • Using Assertions • Compiling Files That Use Assertions • Enabling

Outline • Introduction • Using Assertions • Compiling Files That Use Assertions • Enabling & Disabling Assertions 10

Using Assertions • Do not use assertions for: argument checking in public methods. Argument

Using Assertions • Do not use assertions for: argument checking in public methods. Argument checking is part of the method’s published specifications (or contract): Specifications are obeyed whether or not assertions are enabled. • Assert’s expression should have no sideeffects. Exception: assertions can modify state used only from within other assertions (illustrated later). 11

Internal Invariants Replace With if ( i % 3 == 0 ) {. .

Internal Invariants Replace With if ( i % 3 == 0 ) {. . . } else if ( i % 3 == 1 ) {. . . } else { // We know ( i % 3 == 2 ). . . } {. . . } else { assert i % 3 == 2 : i; . . . } // assert fails for i = -5 12

Control-Flow Invariants Use: assert false; // an unreachable point Replace With void foo() {

Control-Flow Invariants Use: assert false; // an unreachable point Replace With void foo() { { for (. . . ) { { if (. . . ) return; } } // unreachable point assert false; // unreachable } 13

Control-Flow Invariants Use: assert false; // an unreachable point • The foregoing only makes

Control-Flow Invariants Use: assert false; // an unreachable point • The foregoing only makes sense if reaching a point is possible but erroneous. • If it is impossible, the compiler handles it. • If it is possible, you may always throw an exception Not just when assertions are enabled. Replace “assert false; ” with “throw new Assertion. Error(); ” 14

Preconditions • Do not assert method contracts /** * Sets the refresh rate. *

Preconditions • Do not assert method contracts /** * Sets the refresh rate. * @param rate refresh rate, in frames per second. * @throws Illegal. Argument. Exception if rate <= 0 or * rate > MAX_REFRESH_RATE. */ public void set. Refresh. Rate(int rate) { // Enforce specified precondition in public method if (rate <= 0 || rate > MAX_REFRESH_RATE) throw new Illegal. Argument. Exception("Illegal rate: " + rate); set. Refresh. Interval(1000/rate); } 15

Preconditions … • Assert a nonpublic method's precondition. • An assertion is appropriate in

Preconditions … • Assert a nonpublic method's precondition. • An assertion is appropriate in the following “helper” method invoked by the previous method. 16

/** * Sets the refresh interval (to a legal frame rate). * @param interval

/** * Sets the refresh interval (to a legal frame rate). * @param interval refresh interval in milliseconds. */ private void set. Refresh. Interval( interval ) { // Confirm adherence to precondition in nonpublic method assert interval > 0 && interval <= 1000/MAX_REFRESH_RATE : interval; . . . // Set the refresh interval } The assertion can fail if MAX_REFRESH_RATE > 1000. 17

Lock-Status Precondition Original private Object[] a; public synchronized int find(Object key) { return find(key,

Lock-Status Precondition Original private Object[] a; public synchronized int find(Object key) { return find(key, a, 0, a. length); } // Recursive helper method: always has lock on this private int find(Object key, Object[] arr, int start, int len) {. . . } Assert lock status: // Recursive helper method: always has lock on this. private int find(Object key, Object[] arr, int start, int len) { // lock-status assertion assert Thread. holds. Lock(this); . . . } 18

Postconditions Replace void push( Object o ) { With void push( Object o )

Postconditions Replace void push( Object o ) { With void push( Object o ) { … … stack. add( ++top, o ); // top == stack. size(); assert top == stack. size() : “top: ” } + top + “, size: ” + stack. size(); } 19

Postconditions … • An assert’s expression may need state. void foo(int[] array) { //

Postconditions … • An assert’s expression may need state. void foo(int[] array) { // Manipulate array. . . // At this point, array contents == itself // prior to manipulation } Replace the above with the following. 20

Postconditions … void foo(final int[] array) { // Inner class that saves state &

Postconditions … void foo(final int[] array) { // Inner class that saves state & performs final consistency check class Data. Copy { private int[] array. Copy; Data. Copy() { array. Copy = ( int[] ) array. clone(); } boolean is. Consistent() { return Arrays. equals( array, array. Copy ); } } Data. Copy copy = null; // Always succeeds; has side effect of saving a copy of array assert ( ( copy = new Data. Copy() ) != null ); // copy only if ea. . . // Manipulate array // Ensure array has same ints in same order as before. assert copy. is. Consistent(); 21 }

Class State Invariants • Class state invariant: an invariant that applies to all instances

Class State Invariants • Class state invariant: an invariant that applies to all instances at the beginning & ending of all methods. E. g. , in a balanced tree, a class invariant is that the tree is balanced. • Style: combine the expressions that check required constraints into an internal method. // Returns true if this tree is properly balanced private boolean is. Balanced() {. . . } • Assert class invariant just prior to return from public methods & constructors: assert is. Balanced(); 22

Outline • Introduction • Using Assertions • Compiling Files That Use Assertions • Enabling

Outline • Introduction • Using Assertions • Compiling Files That Use Assertions • Enabling & Disabling Assertions • Compatibility with Existing Programs 23

Compiling Files That Use Assertions To tell javac to accept assertions, use the source

Compiling Files That Use Assertions To tell javac to accept assertions, use the source 1. 4 command-line option: javac -source 1. 4 My. Class. java 24

Outline • Introduction • Using Assertions • Compiling Files That Use Assertions • Enabling

Outline • Introduction • Using Assertions • Compiling Files That Use Assertions • Enabling & Disabling Assertions 25

Enabling & Disabling Assertions • • By default, assertions are disabled. Enable assertions, using

Enabling & Disabling Assertions • • By default, assertions are disabled. Enable assertions, using the -ea, switch. Disable assertions, using the -da, switch. Specify granularity as the switch argument: • no arguments Enables/disables assertions in all classes except system classes. • package. Name. . . Enables/disables assertions in the package & any subpackages. • . . . Enables/disables assertions in the unnamed package in the current working directory. • class. Name Enables/disables assertions in the named class. 26

Enabling & Disabling Assertions • To run Bat. Tutor, with assertions enabled in only

Enabling & Disabling Assertions • To run Bat. Tutor, with assertions enabled in only package com. wombat. fruitbat & its subpackages: java -ea: com. wombat. fruitbat. . . Bat. Tutor • To run Bat. Tutor with assertions: – enabled in package com. wombat. fruitbat – disabled in class com. wombat. fruitbat. Brickbat: java -ea: com. wombat. fruitbat. . . da: com. wombat. fruitbat. Brickbat Bat. Tutor 27

Enabling & Disabling Assertions To (en/dis)able system class assertions, use: -esa -dsa To run

Enabling & Disabling Assertions To (en/dis)able system class assertions, use: -esa -dsa To run Bat. Tutor with assertions: • enabled in system classes, • enabled in the com. wombat. fruitbat package & its subpackages: java -esa -ea: com. wombat. fruitbat. . . Bat. Tutor 28