Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014."— Presentation transcript:

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

2 Contracts Client and Supplier Contract: –if client satisfies certain preconditions, then the supplier will produce a product satisfying certain postconditions Copyright W. Howden26/4/2014

3 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 6/4/2014Copyright W. Howden3

4 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 6/4/2014Copyright W. Howden4

5 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 6/4/2014Copyright W. Howden5

6 Assertions and Preconditions Assertion should appear as first line in a method Asserts that whenever execution reaches this location, this property must be true 6/4/2014Copyright W. Howden6

7 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 6/4/2014Copyright W. Howden7

8 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 6/4/2014Copyright W. Howden8

9 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. Howden96/4/2014

10 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. Howden106/4/2014

11 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. Howden116/4/2014

12 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. Howden126/4/2014

13 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 6/4/2014Copyright W. Howden13

14 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 6/4/2014Copyright W. Howden14

15 Copyright W. Howden15 Partial Correctness and Termination Suppose that A 1 is the precondition for a method m and A n is the postcondition. Correctness: m is totally correct if it is partially correct and it always terminates Definition of partial correctness: if A 1 is true at the beginning of an execution and if m is executed and terminates, then A n will be true at the end of the execution 6/4/2014

16 Copyright W. Howden16 Proof Technique Add intermediate assertions A i 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 6/4/2014

17 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 6/4/2014Copyright W. Howden17

18 Copyright W. Howden18 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 6/4/2014

19 Copyright W. Howden196/4/2014

20 Copyright W. Howden20 Verification Conditions for 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 6/4/2014

21 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. 6/4/2014Copyright W. Howden21

22 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 6/4/2014Copyright W. Howden22

23 Copyright W. Howden23 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 6/4/2014

24 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 Code suppose to figure out current year. –e.g. if days = 500 it must be /4/2014Copyright W. Howden24

25 Zune Related Code year = ORIGINYEAR; /* = 1980 */ while (days > 365 ) { if isLeapYear(year)) { if (days > 366) { days -= 366; year += 1; } else { days -= 365; year += 1; } 6/4/2014Copyright W. Howden25

26 (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, 6/4/2014Copyright W. Howden26

27 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 6/4/2014Copyright W. Howden27

28 isMember() with Verification Assertions 6/4/2014Copyright W. Howden28 public boolean isMember(String name) { /** Pre: for j = 0 to numberMembers-1 membersData[j].name != null /** numberMembers -1 >=0 for (int i=0; i <= numberMembers-1; ++i) {/** for j = 0 to i-1 membersData[j].name != name /** i <= numberMembers-1 if (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

29 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 6/4/2014Copyright W. Howden29

30 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 6/4/2014Copyright W. Howden30

31 deleteMember() 6/4/2014Copyright W. Howden31 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; }

32 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 6/4/2014Copyright W. Howden32

33 Intermediate Assertions All intermediate assertions except –return/exit assertion for second return –final assertion to summarize both return assertions 6/4/2014Copyright W. Howden33

34 6/4/2014Copyright W. Howden34 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; }

35 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 6/4/2014Copyright W. Howden35

36 deleteMember() with Second Pre-Return Assertion 6/4/2014Copyright W. Howden36 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; }

37 Sample Reasoning about Second Pre-Return Assertion If we have the case where i is not numberMembers-1 If we use the above along with the first while-loop intermediate assertion, we can get the second pre-return assertion 6/4/2014Copyright W. Howden37

38 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 6/4/2014Copyright W. Howden38

39 Continued Reasoning The two pre return intermediate assertions imply the final intermediate assertion The final intermediate assertion gives us the Postcondition 6/4/2014Copyright W. Howden39

40 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 loop while (!(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 6/4/2014Copyright W. Howden40

41 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 6/4/2014Copyright W. Howden41

42 Dynamic Analysis Use Java assertions and testing to verify contracts assert Expression 1 ; assert Expression 1 : Expression 2 ; –If Expression 1 is false then system will throw an error. Value of Expression 2 is returned can be turned off and on using a command line switch 6/4/2014Copyright W. Howden42

43 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 6/4/2014Copyright W. Howden43

44 Inserting Assertions - Postconditions Should occur before each return Use a function to facilitate the situation where there are multiple returns, each requiring the postcondtion 6/4/2014Copyright W. Howden44

45 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 6/4/2014Copyright W. Howden45

46 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 6/4/2014Copyright W. Howden46

47 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(). 6/4/2014Copyright W. Howden47

48 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 6/4/2014Copyright W. Howden48

49 6/4/2014Copyright W. Howden49 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; }

50 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 6/4/2014Copyright W. Howden50

51 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 6/4/2014Copyright W. Howden51

52 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 6/4/2014Copyright W. Howden52


Download ppt "Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014."

Similar presentations


Ads by Google