Objects, Design, and Concurrency Formal Analysis of Software Artifacts

Objects, Design, and Concurrency Formal Analysis of Software Artifacts

Principles of Software Construction: Objects, Design, and Concurrency Formal Analysis of Software Artifacts Jonathan Aldrich Charlie Garrod School of Computer Science © 2012-2013 W Scherlis, J Aldrich, C Garrod, and C Kästner Back to Testing • Piazza Question: How can I automatically test making good moves when the player gets random tiles? • Answer: Design your game with testing in mind • Your ideas? • E.g. Provide a method to set the random seed • In tests, the seed determines each player’s tiles • Look at those tiles, and design your tests accordingly • In real executions, seed based on time, or other data • E.g. Provide a method to replace tiles with known ones • Only used in testing 15-214 7 Testing and Proofs • Testing (Validation) • Proofs (Verification) ° Observable properties ° Any program property ° Verify program for one ° Verify program for all execution executions ° Manual development with ° Manual development with automated regression automated proof checkers ° Most practical approach now ° Practical for small programs, may scale up in the future • So why study proofs if they aren’t (yet) practical? • Proofs tell us how to think about program correctness • Important for development, inspection, dynamic assertions • Foundation for static analysis tools • These are just simple, automated theorem provers • Many are practical today! 15-214 8 Dafny Class Invariants - from the Previous Lecture A Dafny function is used in class SimpleSet { specifications. It cannot be called (though function methods can) var contents: array <int >; var size: int ; valid() represents the class invariant. It must be explicitly added to: function valid() : bool • The constructor postcondition reads this , contents; • The precondition of functions and methods {size >= 0 • The postcondition of methods that modify this && contents != null && contents.Length >= size } The reads clause of a function defines the objects on whose fields In this case the class invariant the function’s value depends. This asserts that: is so Dafny can determine when a • The size is non-negative function’s value might be affected • The contents array is non-null by a field write. • The contents array is big 9 15-214 enough to hold size elements Dafny Constructors - from the Previous Lecture An ordinary method can be called method init(capacity: int ) to initialize an object in Dafny. Here, init acts like a constructor. requires capacity >=0; modifies this ; We have to say what objects each method modifies . That way Dafny ensures valid(); knows that previous assertions about the object might no longer ensures size == 0; be true. ensures contents.Length == capacity; ensures fresh (contents); The constructor establishes the class invariant , so valid() is in the { postcondition (the ensures clause). valid() is not in the contents := new int [capacity]; precondition because the object is uninitialized before calling init. size This:= 0;helps Dafny to know that } contents does not alias an external array. If it did, we could mess up the invariants of SimpleSet by writing to the external array. 15-214 10 Specifying a Method in Dafny - from the Previous Lecture method add(i:int) Typically methods other than the constructor need to assume the requires valid(); class invariant holds. requires size < contents.Length || i in mset(); modifies this , contents; This methodThis is modifies the main the effect receiver of object andthe itsmethod—changing constituent array. the ensures valid(); mathematical set this ensures mset() == old (mset()) + {i}; objectSince represents we modified the object we need to assert ensures contents == old (contents); the class invariant again ensures i in old (mset()) ==> size == old (size); ensures !(i in old (mset())) ==> size == old (size)+1; { … } The identity of the contents array did not change Size is incremented iff the element was not in the mathematical set represented by this SimpleSet when the method was called 15-214 11 Reference: mset() - from the Previous Lecture function mset() : set<int> reads this, contents; requires valid(); { set j:int | 0 <= j < size :: contents[j] } 15-214 12 Reference: contains() - from the Previous Lecture method contains(i:int) returns (b: bool) requires valid(); ensures b <==> i in mset(); {var j := 0; while (j < size) invariant 0 <= j <= size; invariant !(i in set k:int | 0 <= k < j :: contents[k]); decreases size - j; { if (contents[j] == i) { return true; } j := j + 1; } return false; 15-214} 13 Behavioral Subtyping (Liskov Substitution Principle) Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T. Barbara Liskov • An object of a subclass should be substitutable for an object of its superclass • Known already from types: • May use subclass instead of superclass • Subclass can add, but not remove methods • Overridden method must return same or supertype • Overridden method may not throw additional exceptions • Applies more generally to behavior: • A subclass must fulfill all contracts that the superclass does • Same or stronger invariants • Same or stronger postconditions for all methods • Same or weaker preconditions for all methods 15-214 14 Behavioral Subtyping (Liskov Substitution Principle) abstract class Vehicle { class Car extends Vehicle { int speed, limit; int fuel; //@ invariant speed < limit; boolean engineOn; //@ invariant fuel >= 0; //@ requires speed != 0; //@ ensures |speed| < |\old{speed}| //@ requires fuel > 0 && ! engineOn; void break(); //@ ensures engineOn; } void start() { … } void accelerate() { … } //@ requires speed != 0; //@ ensures |speed| < |\old{speed}| void break() { … } } Subclass fulfills the same invariants (and additional ones) Overridden method has the same pre and postconditions 15-214 15 Behavioral Subtyping (Liskov Substitution Principle) class Car extends Vehicle { class Hybrid extends Car { int fuel; int charge; boolean engineOn; //@ invariant charge >= 0; //@ invariant fuel >= 0; //@ requires (charge > 0 || fuel > 0) //@ requires fuel > 0 && ! engineOn; && ! engineOn; //@ ensures engineOn; //@ ensures engineOn; void start() { … } void start() { … } void accelerate() { … } void accelerate() { … } //@ requires speed != 0; //@ requires speed != 0; //@ ensures |speed| < |\old{speed}| //@ ensures |speed| < |\old{speed}| void break() { … } //@ ensures charge > \old{charge} } void break() { … } } Subclass fulfills the same invariants (and additional ones) Overridden method start has weaker precondition Overridden method break has stronger postcondition 15-214 16 Behavioral Subtyping (Liskov Substitution Principle) class Rectangle { class Square extends Rectangle { int h, w; Square(int w) { super(w, w); Rectangle(int h, int w) { } this.h=h; this.w=w; } } //methods } Is Square a behavior subtype of Rectangle? 15-214 17 Behavioral Subtyping (Liskov Substitution Principle) class Rectangle { class Square extends Rectangle { //@ invariant h>0 && w>0; //@ invariant h==w; int h, w; Square(int w) { super(w, w); Rectangle(int h, int w) { } this.h=h; this.w=w; } } //methods } Is Square a behavior subtype of Rectangle? 15-214 18 Behavioral Subtyping (Liskov Substitution Principle) class Rectangle { class Square extends Rectangle { //@ invariant h>0 && w>0; //@ invariant h==w; int h, w; Square(int w) { super(w, w); Rectangle(int h, int w) { } this.h=h; this.w=w; } } void scale(int factor) { w=w*factor; h=h*factor; } } Is Square a behavior subtype of Rectangle? 15-214 19 Behavioral Subtyping (Liskov Substitution Principle) class Rectangle { class Square extends Rectangle { //@ invariant h>0 && w>0; //@ invariant h==w; int h, w; Square(int w) { super(w, w); Rectangle(int h, int w) { } this.h=h; this.w=w; } } void scale(int factor) { w=w*factor; h=h*factor; } void setWidth(int neww) { w=neww; } } Is Square a behavior subtype of Rectangle? 15-214 20 Behavioral Subtyping (Liskov Substitution Principle) class Rectangle { class Square extends Rectangle { //@ invariant h>0 && w>0; //@ invariant h==w; int h, w; Square(int w) { super(w, w); Rectangle(int h, int w) { } this.h=h; this.w=w; } } void scale(int factor) { w=w*factor; h=h*factor; } void setWidth(int neww) { ← Invalidates stronger w=neww; } invariant (w==h) in subclass } With these methods, Square is not a behavior subtype of Rectangle 15-214 21 Formal Analysis Summary • Specification between textual and formal specifictions • Proving (e.g. with Dafny) vs. Testing • Class Invariants and Behavioral Subtyping • Tools such as Dafny can make proofs more practical • Reduces effort relative to proof by hand • Still considerable work in writing specifications and invariants • Can be useful in documenting code and finding errors • The current tool may miss some defects 15-214 22.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    17 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us