copyright w. howden1 programming by contract cse 111 6/4/2014

52
Copyright W. Howden 1 Programming by Contract CSE 111 06/26/22

Upload: trista-haggett

Post on 29-Mar-2015

214 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Copyright W. Howden 1

Programming by Contract

CSE 111

04/10/23

Page 2: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Contracts

• Client and Supplier

• Contract:– if client satisfies certain preconditions, then the

supplier will produce a product satisfying certain postconditions

Copyright W. Howden 204/10/23

Page 3: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Design by Contract

• All of the components (classes, methods and procedures) have a stated contract that they will fulfill

• Benefits– reusable components– correct interfaces when integrating components– predictable results

04/10/23 Copyright W. Howden 3

Page 4: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Software Contracts

• Methods and procedures• precondition: required input properties

• postconditions: guaranteed output properties, provided precondition is satisfied

• Classes• method contracts

• class invariants– properties that are true on completion of constructor and

true before and after each method application

04/10/23 Copyright W. Howden 4

Page 5: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Assertions

• Expected properties of program state (values of variables)

• Used to specify preconditions, postconditions and class invariants

• Also used for intermediate assertions– statements about what is expected to be true at

intermediate points in a programs execution

04/10/23 Copyright W. Howden 5

Page 6: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Assertions and Preconditions• Assertion should appear as first line in a

method

• Asserts that whenever execution reaches this location, this property must be true

04/10/23 Copyright W. Howden 6

Page 7: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Assertions and Postconditions

• Executable dynamic testing assertions should appear before each return statement

• State that the asserted property is true whenever the program returns from that location

• Static assertions can be put after the return points

04/10/23 Copyright W. Howden 7

Page 8: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Assertions and Class Invariants

• Should appear as postconditions in constructors and all other methods

• Should appear as preconditions in all methods

• For public methods, input should be checked directly and not by an assertion– assertions can be turned off after debugging

04/10/23 Copyright W. Howden 8

Page 9: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Assertion Languages

• Static analysis– non-executable

• informal prose statements or formal statements in a formal logic

• Dynamic analysis• executable expressions that return T or F

• executed during testing, but turned off during production use

Copyright W. Howden 904/10/23

Page 10: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Validating Contracts

• Static: – prove that if the precondition holds then when the

program reaches termination, the postcondition holds

• Dynamic: – use executable assertions for pre and postconditions. Run

tests. If a postcondition does not hold when the precondition holds, the contract is not valid. If a precondition does not hold either a test is faulty or the program and/or precondition need to be corrected

Copyright W. Howden 1004/10/23

Page 11: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Lecture Topics

• Static analysis(verification) of method/procedure and class contracts– sometimes called “proofs of correctness”

• Dynamic analysis (testing) with Java assertions– pre and postconditions– class invariants, etc.

Copyright W. Howden 1104/10/23

Page 12: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Why Learn About Proofs?

• For new complex logic, invaluable check against reasoning flaws

• Even if never formally done, provides a way of looking at a program that can guide code reading, or informal analysis

• Are the means of proving properties of standard algorithms (e.g. sorting)

Copyright W. Howden 1204/10/23

Page 13: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Beams and Girders

• Proved algorithms and state models are the “beams and girders” of a software construction project

• These are the pieces with proved properties that we can rely on

• Abstract, so must be translated into programming language code

• Construction involves using these to build a specific application product

04/10/23 Copyright W. Howden 13

Page 14: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Informal and Formal Proofs

• Informal• “precise” state assertions, but not in a formal logical

language

• similar to the language of informal mathematics

• Formal• uses formal semantics for programming language

statements

• very detailed, and hard to construct

04/10/23 Copyright W. Howden 14

Page 15: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Copyright W. Howden 15

Partial Correctness and Termination

• Suppose that A1 is the precondition for a method m and An is the postcondition.

• Correctness: m is totally correct if it is partially correct and it always terminates

• Definition of partial correctness:• if A1 is true at the beginning of an execution and if

m is executed and terminates, then An will be true at the end of the execution

04/10/23

Page 16: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Copyright W. Howden 16

Proof Technique

• Add intermediate assertions Ai to the method.– breaks down proof into easily handled chunks

• Make sure that each loop has at least one intermediate assertion

• For each pair of assertions (X,Y) where there is a subpath p from X to Y, which has no other assertions on it, prove its verification condition:

“if X is true at the beginning of p, and p is executed, then Y will be true at the end of p”

04/10/23

Page 17: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Proof Method Validity?

• Consider any execution path P

• P can be broken up into a sequence of subpaths p, which go from one assertion to the next with no assertion in between

• If all of the verification conditions for the subpaths are true, we can join them together to provide a proof for the whole path

04/10/23 Copyright W. Howden 17

Page 18: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Copyright W. Howden 18

Verification Example

• Program multiplies two numbers x and y by adding up y x times

• Input (precondition) assertion Pre, output (postcondition) assertion Post, intermediate loop invariant assertion IA

04/10/23

Page 19: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Copyright W. Howden 1904/10/23

Page 20: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Copyright W. Howden 20

Verification Conditionsfor Example

• Prove that 1. if Pre is true then IA will be true

2. if IA is true and Count = 0 then Post will be true

3. If IA is true and Count 0 then IA will be true

04/10/23

Page 21: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Proof of Verification Condition 3

Suppose that we are at IA and

x*y = Product + Count*Y

is true. If we go around the loop, Product is incremented by y, and Count is decremented by 1. This means the expression on the right would get larger by y, and then smaller by y, leaving its value the same. So if the relationship was true before the loop, it will also be true after the loop.

04/10/23 Copyright W. Howden 21

Page 22: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Termination Proofs

• If there are no loops in m, and all called methods are terminate, then m must terminate

• For loops, look for a counter that approaches an upper (lower) limit and is incremented (decremented) on every path through the loop

04/10/23 Copyright W. Howden 22

Page 23: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Copyright W. Howden 23

Termination Proof for Multiply Example

• Count initialized to x >=0

• Loop terminates if Count == 0

• For each iteration Count is decremented by 1 so loop must terminate

• Note: • if Precondition x>=0 is removed from example and

input x can be negative, algorithm will not always terminate (i.e. when x < 0), but program is still partially correct

04/10/23

Page 24: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Termination Bug Example

• Application: MS Zune MM player

• Failure: December 31, 2008, device would not boot – infinite loop

• Faulty procedure– Input = day count relative to origin year 1980.

Code suppose to figure out current year.– e.g. if days = 500 it must be 1982

04/10/23 Copyright W. Howden 24

Page 25: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Zune Related Code

year = ORIGINYEAR; /* = 1980 */

while (days > 365 )

{

if isLeapYear(year))

{

if (days > 366)

{

days -= 366;

year += 1;

}

}

else

{

days -= 365;

year += 1;

}

}

04/10/23 Copyright W. Howden 25

Page 26: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

(Attempted) Termination Proof

• Decremented counter: days

• Termination condition: days <= 365

• When traversing loop, if year is a leap year, and days (remaining) is = 366, then the loop is traversed with no changes to the counter (days)

• i.e. there is a path through the loop on which the counter is not decremented,

04/10/23 Copyright W. Howden 26

Page 27: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Examples from DS

• isMember() checks to see if DB in-memory vector has an entry with a given name. Our assertions capture what the program is supposed to do

• deleteMember() is more complex

04/10/23 Copyright W. Howden 27

Page 28: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

isMember() with Verification Assertions

04/10/23 Copyright W. Howden 28

public boolean isMember(String name){ /** Pre: for j = 0 to numberMembers-1 membersData[j].name != null

/** numberMembers -1 >=0for (int i=0; i <= numberMembers-1; ++i){ /** for j = 0 to i-1 membersData[j].name != name

/** i <= numberMembers-1if (name.equals(membersData[i].name)){ return true;

/** Post 1: return = true/** for j = 0 to i-1 membersData[j].name != name/** membersData[i].name = name

}/** return false;/** Post 2: return = false/** for j = 0 to numberMembers-1 membersData[j].name != name

Page 29: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Verification of IsMember()

• It is fairly simple to reason that for all pairs of assertions, if the first is true and you reach the next one, it is true also

• Hence if the precondition holds, and the program terminates, the postcondition will

• So the contract is valid

• But we also need to consider termination

04/10/23 Copyright W. Howden 29

Page 30: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Termination of isMember()

• Termination is easy because the loop counts up to a limit from 0 and the precondition

/** numberMembers -1 >=0

requires the limit to be larger than the initial value

• Note: this precondition clause was added during analysis!!

• I had not thought of this

04/10/23 Copyright W. Howden 30

Page 31: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

deleteMember()

04/10/23 Copyright W. Howden 31

public boolean deleteMember(String name){

int i = 0;while (!(name.equals(membersData[i].name)) & (i <= numberMembers-1)){ ++i;}if (i <= numberMembers-1){

for (int j = i; j< numberMembers-1; ++j){

membersData[j]=membersData[j+1];}--numberMembers;return true;

}else{ return false;}

}

Page 32: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

deleteMember() - Pre and Post Conditions

notation: x’ means new value of x, versus original or previous value

contents stands for the collection of items in the designated data structure

Precondition

/* for k = 1 to numberMembers-1 membersData[k] non null, membersData.name field is a string

/* name is of type string

/* numberMembers >=0

Postcondition

/** if there exists some k, 1 <= k <= numberMembers – 1 such that memberData[k].name = name

/** numberMembers’ = numberMembers – 1 and

/** contents(memberData[j]’, 1<= j <= numberMembers-1’)

= contents(memberData[j], 1<= j <= numberMembers) ~ memberData[k]

/** if there does not exist some k, 1 <= k <= numberMembers – 1 such that memberData[k].name = name

/** numberMembers’ = numberMembers

/** for j = 1 to numberMembers-1, membersData[j]’ = membersData[j]

/** return false

04/10/23 Copyright W. Howden 32

Page 33: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Intermediate Assertions

• All intermediate assertions except– return/exit assertion for second return– final assertion to summarize both return

assertions

04/10/23 Copyright W. Howden 33

Page 34: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

04/10/23 Copyright W. Howden 34

public boolean deleteMember(String name){

int i = 0;while (!(name.equals(membersData[i].name)) & (i <= numberMembers-1)){ /** for j = 0 to i, name != membersData[j].name

/** i <= numberMembers-1/** for j = 0 to membersData – 1, membersData[j]’ = membersData[j]++i;

}if (i <= numberMembers-1){ /** for j = 0 to i-1, name != membersData[j].name

/** i <= numberMembers-1/** name == membersData[i].name

for (int j = i; j< numberMembers-1; ++j){

membersData[j]=membersData[j+1];/** for k = 1 to i-1, membersData[k]’ =membersData[k];/** for k = i to j, membersData[k]’ = membersData[k+1]

} /** for k = 1 to i-1, membersData[k]’ =membersData[k];/** for k = i to numberMembers-2, membersData[k]’ = membersData[k+1]--numberMembers;return true;

}else{ return false;}

}

Page 35: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Sample Reasoning About First Pre-Return Assertion

• First part follows directly from the intermediate assertion in the loop

• Second part follows from the second intermediate assertion plus the following

• if the loop was entered, then the final value of j on exit must have been numberMembers-2

• if we did not enter the loop then i must have been numberMembers-1 so it is vacuously true

04/10/23 Copyright W. Howden 35

Page 36: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

deleteMember() with Second Pre-Return Assertion

04/10/23 Copyright W. Howden 36

public boolean deleteMember(String name){

int i = 0;while (!(name.equals(membersData[i].name)) & (i <= numberMembers-1)){ ++i;}if (i <= numberMembers-1){

for (int j = i; j< numberMembers-1; ++j){

membersData[j]=membersData[j+1];}--numberMembers;return true;

}else/** for j = 0 to numberMembers - 1, memberData[j].name != name{ return false;}

}

Page 37: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Sample Reasoning about Second Pre-Return Assertion

• If we have the case where i is not <= numberMembers-1 then it must be > numberMembers-1

• If we use the above along with the first while-loop intermediate assertion, we can get the second pre-return assertion

04/10/23 Copyright W. Howden 37

Page 38: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Final “Intermediate” Assertions

• Assertion to go just after last “}” /** return = true

/** i <= numberMembers-1

/** membersData[i].name = name

/** for k = 1 to i-1 membersData[k]’ =membersData[k];

/** for k = i to numberMembers-2 membersData[k]’ = membersData[k+1]

/** numberMembers’ = nuumberMembers - 1;

/* or

/** return false

/** not (i <= numberMembers-1)

/** for k = 1 to numberMembers-1 membersData[k].name != name

/** for k = 1 to i-1 membersData[k]’ =membersData[k];

/** numberMembers’ = numberMembers

04/10/23 Copyright W. Howden 38

Page 39: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Continued Reasoning

• The two pre return intermediate assertions imply the final intermediate assertion

• The final intermediate assertion gives us the Postcondition

04/10/23 Copyright W. Howden 39

Page 40: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Oops?

• Consider the precondition/* for k = 1 to numberMembers-1 membersData[k] is non null, and membersData.name is a string

/* name is of type string

/* numberMembers >=0

• Now look at the first loopwhile (!(name.equals(membersData[i].name)) & (i <= numberMembers-1))

{ ++i;

}

• It is possible to reference membersData[i] with i = numberMembers, and the precondition does not guarantee that it has a non-null value!

• This is an actual bug that causes a failure

04/10/23 Copyright W. Howden 40

Page 41: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Moral of the Story

• Proofs of correctness forces you to think through the logic of a complex algorithm, but it is error prone for dealing with the details of an actual program

• In this case, assume that all vectors are infinite, that we can compare a given value with a non-value, etc., and the problem goes away

04/10/23 Copyright W. Howden 41

Page 42: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Dynamic Analysis

• Use Java assertions and testing to verify contracts

• assert Expression1 ;

• assert Expression1 : Expression2 ;

– If Expression1 is false then system will throw an error. Value of Expression2 is returned

• can be turned off and on using a command line switch

04/10/23 Copyright W. Howden 42

Page 43: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Inserting Assertions - Preconditions

• Precondition is first line of code, consisting of expression in input parameters

• Public methods should check input and throw an illegal argument exception, rather than have this checked with an assertion

• methods should protect themselves from bad data even after testing has been completed

04/10/23 Copyright W. Howden 43

Page 44: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Inserting Assertions - Postconditions

• Should occur before each return

• Use a function to facilitate the situation where there are multiple returns, each requiring the postcondtion

04/10/23 Copyright W. Howden 44

Page 45: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Inserting Assertions – Class Invariants

• True before and after each method

• Insert in methods as postconditions

• Class state changed by method call?– No: not necessary to check invariant at

beginning of methods – Yes: (e.g. class has public class variables) then

include invariant in methods as a precondition

04/10/23 Copyright W. Howden 45

Page 46: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Using Assertions with Testing

• Construct tests using methods such as– black box: normal and oddball inputs – coverage: make sure all statements or branches

executed at least once

• Do not have to manually observe outputs to determine if tests passed if we can rely on the postconditions to catch bad output

04/10/23 Copyright W. Howden 46

Page 47: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

DS Example - IsMember

• No precondition assertions, but insert code to confirm validity of input data

• For output check need to essentially rewrite the code inside a method called by the postcondition assertion– Define a method called noMatch().

04/10/23 Copyright W. Howden 47

Page 48: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Technical Details

• Defined the method “noMatch()” inside a new inner class called memberDataProps

• Want to only create the memberDataProps instance when assertions are turned on (say during testing) so create with an assignment inside a dummy assertion

04/10/23 Copyright W. Howden 48

Page 49: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

04/10/23 Copyright W. Howden 49

public boolean isMember(String name){ class memberDataProps

{ public boolean noMatch(memberData[] m, int length) { for (i= 0; length-1; ++i;)

{ if (name.equals(m[i].name)) return false;}

return true; }

}memberDataProps checker; assert ((checker = new memberDataProps()) != null); if (numberMembers-1 < 0) throw new IllegalArgumentException(“Out of range parameter”); for (int i=0; i <= numberMembers-1; ++i)

{ if membersData[i] == null throw new IllegalArgumentException(“Null param”);

}for (int i=0; i <= numberMembers-1; ++i)

{ if (name.equals(membersData[i].name)){ assert name.equals(membersData[i].name);

return true;}

}assert checker.noMatch(membersData, numberMembers);return false;

}

Page 50: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Useful?

• Will use of assertions here lead to defect detection?

• Having to essentially rewrite the method inside the noMatch() method seems shaky.– maybe it would have the same bugs as the code

04/10/23 Copyright W. Howden 50

Page 51: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

deleteMember()

• Could use postconditions that:• for false, check that vector items are the same, and

numberMembers is unchanged

• for true, check that the deleted element not in the list, and the contents are the same except for deleted element. Also numberMembers is decremented

• Document expected loop bounds invariant.• With a good set of tests this is what will find the

problem

04/10/23 Copyright W. Howden 51

Page 52: Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014

Assignment 11

• Choose two classes from your phase 1 that you are going to reuse (select non trivial examples)– Prove their correctness using informal

assertions– Construct executable assertions and run tests

against them

04/10/23 Copyright W. Howden 52