Testing, Debugging, and Verification

Similar documents
Formal Methods for Software Development

Formal Specification and Verification

Lecture 10 Design by Contract

Formal Methods for Software Development

The Java Modeling Language a Basis for Static and Dynamic Verification

Formale Entwicklung objektorientierter Software

Assertions & Design-by-Contract using JML Erik Poll University of Nijmegen

Assertions, pre/postconditions

Induction and Semantics in Dafny

Software Engineering

Programming with Contracts. Juan Pablo Galeotti, Alessandra Gorla Saarland University, Germany

Software Testing Prof. Meenakshi D Souza Department of Computer Science and Engineering International Institute of Information Technology, Bangalore

Incremental Proof Development in Dafny

Softwaretechnik. Program verification. Albert-Ludwigs-Universität Freiburg. June 28, Softwaretechnik June 28, / 24

The Java Modeling Language JML

Software Engineering Testing and Debugging Testing

Program Verification (6EC version only)

The Java Modeling Language (Part 2)

Advances in Programming Languages

Reasoning About Imperative Programs. COS 441 Slides 10

Part II. Hoare Logic and Program Verification. Why specify programs? Specification and Verification. Code Verification. Why verify programs?

Lecture Notes on Linear Search

Hardware versus software

ESC/Java2 extended static checking for Java Erik Poll Radboud University Nijmegen

JML Class Specifications The Java Modeling Language (Part 2) A Java Class

Case study: compare and swap

Softwaretechnik. Program verification. Software Engineering Albert-Ludwigs-University Freiburg. June 30, 2011

Specifying and Verifying Programs (Part 2)

Overview The Java Modeling Language (Part 1) Related Work

Lecture 1 Contracts : Principles of Imperative Computation (Fall 2018) Frank Pfenning

Shared Variables and Interference

Lecture 1 Contracts. 1 A Mysterious Program : Principles of Imperative Computation (Spring 2018) Frank Pfenning

Static program checking and verification

Shared Variables and Interference

Outline Introduction The Spec# language Running Spec# Tutorials on Spec# Carl Leonardsson 2/

Comparing procedure specifications

Backward Reasoning: Rule for Assignment. Backward Reasoning: Rule for Sequence. Simple Example. Hoare Logic, continued Reasoning About Loops

Chapter 4 Defining Classes I

Exercise 3 Subtyping and Behavioral Subtyping October 13, 2017

CSE331 Winter 2014, Midterm Examination February 12, 2014

JML tool-supported specification for Java Erik Poll Radboud University Nijmegen

TRIAL EXAM C Software Engineering using Formal Methods TDA293 / DIT270

ESC/Java extended static checking for Java Erik Poll, Joe Kiniry, David Cok University of Nijmegen; Eastman Kodak Company

Overview. Verification with Functions and Pointers. IMP with assertions and assumptions. Proof rules for Assert and Assume. IMP+: IMP with functions

Motivation. Correct and maintainable software Cost effective software production Implicit assumptions easily broken

Fondamenti della Programmazione: Metodi Evoluti. Lezione 5: Invariants and Logic

Introduction to JML David Cok, Joe Kiniry, and Erik Poll Eastman Kodak Company, University College Dublin, and Radboud University Nijmegen

Unit Testing as Hypothesis Testing

n Specifying what each method does q Specify it in a comment before method's header n Precondition q Caller obligation n Postcondition

Semantic Analysis. CSE 307 Principles of Programming Languages Stony Brook University

15-122: Principles of Imperative Computation (Section G)

Lecture 4 Searching Arrays

Softwaretechnik. Lecture 08: Testing and Debugging Overview. Peter Thiemann SS University of Freiburg, Germany

CITS5501 Software Testing and Quality Assurance Formal methods

Testing, Debugging, and Verification exam DIT082/TDA567. Day: 9 January 2016 Time: Will be published mid February or earlier

Code Contracts in C#

School of Informatics, University of Edinburgh

Fundamentals of Software Engineering

Integrating verification in programming languages

Lectures 20, 21: Axiomatic Semantics

CS 161 Computer Security

hwu-logo.png 1 class Rational { 2 int numerator ; int denominator ; 4 public Rational ( int numerator, int denominator ) {

Runtime Checking for Program Verification Systems

Ambientes de Desenvolvimento Avançados

Formal Specification and Verification

Softwaretechnik. Lecture 08: Testing and Debugging Overview. Peter Thiemann SS University of Freiburg, Germany

Advances in Programming Languages

Advanced JML Erik Poll Radboud University Nijmegen

List Functions, and Higher-Order Functions

SOFTWARE ENGINEERING DESIGN I

The JML Tool. Faculty of Engineering Pontificia Universidad Javeriana. The JML Tool p.1/23

Goal. Generic Programming and Inner classes. Minor rewrite of linear search. Obvious linear search code. Intuitive idea of generic linear search

Program Verification. Program Verification 307/434

An Annotated Language

Lecture Notes on Contracts

Type Checking and Type Equality

Syntax of Eiffel: a Brief Overview

Warm-Up Problem. Let be a set of well-formed Predicate logic formulas. Let be well-formed Predicate logic formulas. Prove or disprove the following.

Fundamentals of Software Engineering

Commands, and Queries, and Features. Syntax of Eiffel: a Brief Overview. Escape Sequences. Naming Conventions

Java Modeling Language (JML)

ESC/Java2 Warnings David Cok, Joe Kiniry, and Erik Poll Eastman Kodak Company, University College Dublin, and Radboud University Nijmegen

1007 Imperative Programming Part II

Hoare Logic. COMP2600 Formal Methods for Software Engineering. Rajeev Goré

Announcements. Specifications. Outline. Specifications. HW1 is due Thursday at 1:59:59 pm

CS558 Programming Languages

OOP Design by Contract. Carsten Schuermann Kasper Østerbye IT University Copenhagen

Programming Languages 3. Definition and Proof by Induction

CSE 331 Final Exam 3/16/15 Sample Solution

Testing, Debugging, Program Verification

NEER ENGI AUTOMATED TRANSLATION OF VDM-SL TO JML-ANNOTATED JAVA. Electrical and Computer Engineering Technical Report ECE-TR-29

Formal Systems II: Applications

Spark verification features

Lecture Notes on Memory Layout

CS61B Lecture #5: Arrays and Objects

Advances in Programming Languages

Lecture Notes on Arrays

Assertions & Verification Example Exam Questions

From Event-B Models to Dafny Code Contracts

Data abstractions: ADTs Invariants, Abstraction function. Lecture 4: OOP, autumn 2003

Transcription:

Testing, Debugging, and Verification Formal Specification, Part II Srinivas Pinisetty 23 November 2017

Introduction Today: Introduction to Dafny: An imperative language with integrated support for formal specification and verification Methods, assertions, functions and arrays. Classes in Dafny. Pre- and post conditions in Dafny.

Recap: First-Order Logic Recall: FOL extends propositional logic by: Quantifiers: and. Variables and Types (other than bool). (Mathematical) Functions and Predicates (boolean functions) Example: Σ int : T int = {int, bool} F int = {+, } {..., 2, 1, 0, 1, 2,...} P int = {<} α(+) = α( ) = (int, int) int α(<) = (int, int) bool In addition, set of (typed) variables V.

Recap: Boolean Connectives and Quantifiers Formulas are built from (atomic) formulas combined with boolean connectives: FOL Meaning Dafny A not A!A A B A and B A && B A B A or B A B

Recap: Boolean Connectives and Quantifiers Formulas are built from (atomic) formulas combined with boolean connectives: FOL Meaning Dafny A not A!A A B A and B A && B A B A or B A B A B A implies B A ==> B A B A is equivalent of B, A if and only if B A <==> B

Recap: Boolean Connectives and Quantifiers Formulas are built from (atomic) formulas combined with boolean connectives: FOL Meaning Dafny A not A!A A B A and B A && B A B A or B A B A B A implies B A ==> B A B A is equivalent of B, A if and only if B A <==> B x : t. A For all x of type t, A holds. forall x:t ::A x : t. A There exists some x such that A holds. exists x:t ::A

Example FOL formulas Example 1: All entries in the array a are greater than 0 i : int. 0 i < a.length a[i] > 0

Example FOL formulas Example 1: All entries in the array a are greater than 0 i : int. 0 i < a.length a[i] > 0 Example 2: There is at least one prime number in the array a i : int. 0 i < a.length isprime(a[i])

Example FOL formulas Example 1: All entries in the array a are greater than 0 i : int. 0 i < a.length a[i] > 0 Example 2: There is at least one prime number in the array a i : int. 0 i < a.length isprime(a[i]) Exercise: Are the following equivalent to the corresponding examples? Why/why not? 1) i : int. 0 i < a.length a[i] > 0 2) i : int. 0 i < a.length isprime(a[i])

Example FOL formulas Example 1: All entries in the array a are greater than 0 i : int. 0 i < a.length a[i] > 0 Example 2: There is at least one prime number in the array a i : int. 0 i < a.length isprime(a[i]) Exercise: Are the following equivalent to the corresponding examples? Why/why not? 1) i : int. 0 i < a.length a[i] > 0 2) i : int. 0 i < a.length isprime(a[i]) No, consider any -ve value.

Example FOL formulas i : int. 0 i < a.length a[i] > 0 All entries in the array a are greater than 0. consider i = -5 0 5 < a.length a[ 5] > 0 false (P) == true if -5 was a number between 0 and arr.length, then the element index at -5 would be positive i : int. 0 i < a.length a[i] > 0 All numbers are between 0 and arr.length and for each number i if we access arr at that number we get something positive. consider i = -5 0 5 < a.length a[ 5] > 0 false (P) == false -5 is a number between 0 and arr.length and the element index at -5 would be positive

The Dafny language Dafny is an imperative language with integrated support for formal specification and verification. Programming language that enforces for each method that if precondition (Requires) holds then the postcondition (Ensure) must hold In other words: no breaches of contract! no bugs! About Dafny Object oriented, similar to Java. Classes, methods. Methods annotated with pre- and post-conditions, loop invariants... Annotations written in FOL. Specification automatically checked and proved.

The Dafny Language Programming language + Specification language!! Programming language Assignments While loops Methods Executed at runtime Specification language Method pre/post conditions Quantifiers Functions Predicates Used only for checking, ignored at runtime

Classes in Dafny Classes: Keyword class. No access modifiers like public, private as in Java. Fields declared by var keyword (like local variables). Several ways of initialising new objects Constructors Initialisation methods

Classes in Dafny Example: A class in Dafny class } MyClass{ var x : int; // an integer field constructor(init_x : int){...} method Init(init_x : int){...} Example: Declaring an object // Alt 1: Call anon. constructor var myobject := new MyClass(5); // Alt 2: Using Init-method var myobject := new MyClass.Init(5); //Alt 3: Initialise afterwards. var myobject := new MyClass; myobject.init(5);

Dafny variables Variables Declared with keyword var. Types declared by : Assignment written :=. Equality check written ==. Several variables can be declared at once. Parallel assignments possible. Examples: var x : int; x := 34; var y, z := true, false;

Dafny methods and variables Like Java, Dafny has methods. Methods Explicit names for return values. Can refer to return values in specifications. Example: method ManyReturns(x:int,y:int) returns (more:int,less:int )

Assertions: The assert keyword method Abs(x : int) returns ensures 0 <= r; { if (x < 0) {r := -x;} else {r := x;} } method Test(){ var v := Abs(3); assert 0 <= v; (r : int) Placed in the middle of a method. Assertions in Dafny are proven (or rejected) at compile-time, instead of checked at runtime. Use specification language for what to assert. Dafny tries to prove that assertion holds for all executions of the code. Easy, follows from postcondition of Abs

The assert keyword method Abs(x : int) returns ensures 0 <= r; { if (x < 0) {r := -x;} else {r := x;} } method Test(){ var v := Abs(3); assert v == 3; (r : int) Dafny cannot prove this! Why?

The assert keyword method Abs(x : int) returns ensures 0 <= r; { if (x < 0) {r := -x;} else {r := x;} } method Test(){ var v := Abs(3); assert v == 3; (r : int) Dafny cannot prove this! Why? Dafny only remembers the current method body (for efficiency).

The assert keyword method Abs(x : int) returns ensures 0 <= r; { if (x < 0) {r := -x;} else {r := x;} } method Test(){ var v := Abs(3); assert v == 3; (r : int) Dafny cannot prove this! Why? Dafny only remembers the current method body (for efficiency). Dafny only uses annotations (requires and ensures) of other methods to prove things.

The assert keyword method Abs(x : int) returns ensures 0 <= r; { if (x < 0) {r := -x;} else {r := x;} } method Test(){ var v := Abs(3); assert v == 3; (r : int) Dafny cannot prove this! Why? Dafny only remembers the current method body (for efficiency). Dafny only uses annotations (requires and ensures) of other methods to prove things. Inside Test: Dafny only knows that Abs produce a non-negative result!

Exercise: Fixing the specification of Abs Revise the specification of Abs in such a way so that Dafny will manage to prove the assertion assert v == 3. method Abs(x : int) returns (r : int) ensures 0 <= r;... method Test(){ var v := Abs(3); assert v == 3; }

Exercise: Fixing the specification of Abs Revise the specification of Abs in such a way so that Dafny will manage to prove the assertion assert v := 3. method Abs(x : int) returns (r : int) ensures 0 <= r; ensures 0 <= x ==> r == x; ensures x < 0 ==> r == -x;... method Test(){ var v := Abs(3); assert v == 3; } Need to specify exactly what the result is in each case.

Dafny Functions Part of specification language (no assignment, while loop). Cannot modify anything (unlike methods). Safe to use in spec. Can only be used in spec (annotations). Single unnamed return value, body is single statement (no semicolon). A function function abs(x : int) : int { if x < 0 then -x else x } Now, can write e.g.ensures r == abs(x).

Dafny Function Method A function method function method abs(x : int) : int { if x < 0 then -x else x } function method can be used both from spec and programming!!

Predicates Functions returning a boolean are called predicates. A predicate predicate ready()... { insertedcard == null && wrongpincounter == 0 && auth == false; }

Predicates Functions returning a boolean are called predicates. A predicate predicate ready()... { insertedcard == null && wrongpincounter == 0 && auth == false; } Predicates are useful for naming common properties used in many annotations: Example method spitcardout() returns...... ensures ready(); (card : BankCard)

Predicates A predicate is a function giving a boolean A predicate method is a function method giving a boolean

Modifies clauses method enterpin (pin : int) modifies this`auth, this`wrongpincounter, this.insertedcard`valid; Modifies clauses specifies what fields the method may change. Nothing else can be changed. If a method tries to change something not in its modifies clause, Dafny s compiler complains. Saves writing postconditions for fields that never changes. Note: Fields of must be prefixed by the ` (backtick) character in modifies clauses.

Reads Functions must specify what they read. Methods do not have to specify what they read, only what they modify. We will cover this in the next lecture!

Multiple requires (ensures) Vs using && method enterpin (pin : int) requires!customerauth; requires insertedcard!= null; requires insertedcard.valid(); specifies the case where all three preconditions are true in pre-state the above is equivalent to: method enterpin (pin : int) requires (!customerauth && insertedcard!= null && insertedcard.valid());

Parallel for Declare and initialise an array var a := new int[3]; a[0], a[1], a[2] := 0, 0, 0; Parallel assignment: Initialise all entries to 0 forall(i 0 <= i < a.length) {a[i] := 0;} Parallel update: For each index i between 0 and a.length, increment a[i] by 1 forall(i 0 <= i < a.length) {a[i] := a[i] + 1;} Note: All right-hand side expressions evaluated before assignments.

Some Examples Let us try some examples!!

Recall: ATM.dfy class ATM { // fields: var insertedcard : BankCard; var wrongpincounter : int; var customerauth : bool; // Initialisation of ATM objects using a constructor: constructor(){...} // methods: method insertcard (card : BankCard) {... } method enterpin (pin : int) {... }... }

Specifying the Init method for class ATM The Init method is used to initialise new objects: method Init() modifies this; ensures wrongpincounter == 0; ensures auth == false; ensures insertedcard == null; { insertedcard := null; wrongpincounter := 0; auth := false; } All fields of the object are changed: modifies this Postconditions specify initial values.

Informal Specification Very informal Specification of enterpin (pin:int) : Enter the PIN that belongs to the currently inserted bank card into the ATM. If a wrong PIN is entered three times in a row, the card is confiscated and blocked. After having entered the correct PIN, the customer is regarded is authenticated. Implicit: The inserted card is not null. The card is valid to start with (not blocked).

Recall: Specification as Contract Contract states what is guaranteed under which conditions. precondition postcondition postcondition card is inserted, user not yet authenticated, If pin is correct, then the user is authenticated If pin is incorrect and wrongpincounter < 2 then wrongpincounter is increased by 1 and user is not authenticated postcondition If pin is incorrect and wrongpincounter >= 2 then card is confiscated and user is not authenticated Implicit preconditions: inserted card is not null, the card is valid.

Dafny by Example from the file ATM.dfy method enterpin (pin : int) modifies...; requires!customerauth; requires insertedcard!= null; requires insertedcard.valid(); ensures pin == insertedcard.correctpin ==> auth; ensures (pin!= insertedcard.correctpin && wrongpincounter < 2) ==>... ensures (pin!= insertedcard.correctpin && wrongpincounter >= 2) ==>... Three pre-conditions (marked by requires) Three post-conditions (marked by ensures). These are boolean expressions

Dafny by Example Filling in the postconditions... ensures pin == insertedcard.correctpin ==> auth; ensures pin!= insertedcard.correctpin && wrongpincounter < 2 ==>!auth && wrongpincounter == old(wrongpincounter)+1; ensures >= 2 pin!= insertedcard.correctpin && wrongpincounter ==>!auth &&!insertedcard.valid old(e ) means: E evaluated in the pre-state of enterpin, i.e. the value of E before the method was executed.

Mini Quiz: Specifying insertcard The informal specification of insertcard(card:bankcard) is: Inserts a bank card into the ATM if the card slot is free and provided the card is valid. A second method SpitCardOut is specified simply as: Returns the bank card currently inserted in the ATM. Write down a specification for these methods. Recall that the ATM has fields: var insertedcard : BankCard; var wrongpincounter : int; var auth : bool; The BankCard class has fields var pin : int; var accno : int; var valid : bool;

Solutions method insertcard(c : BankCard) modifies this`insertedcard; requires c!= null && c.valid; requires this.insertedcard == null && this.auth == false && this.wrongpincounter ==0; ensures insertedcard == c; method SpitCardOut() returns modifies this; requires insertedcard!= null; ensures card == old(insertedcard); ensures insertedcard == null; ensures wrongpincounter == 0; ensures auth == false; (card : BankCard)

Beyond boolean expressions So far, all annotation has been boolean expressions, e.g. equalities, implications... How to express the following? An array arr only holds values 2.

Beyond boolean expressions So far, all annotation has been boolean expressions, e.g. equalities, implications... How to express the following? An array arr only holds values 2. All BankCard objects have an account number greater than 0.

Beyond boolean expressions So far, all annotation has been boolean expressions, e.g. equalities, implications... How to express the following? An array arr only holds values 2. All BankCard objects have an account number greater than 0. At least one entry in the array is equal to true.

Beyond boolean expressions So far, all annotation has been boolean expressions, e.g. equalities, implications... How to express the following? An array arr only holds values 2. All BankCard objects have an account number greater than 0. At least one entry in the array is equal to true. The variable m holds the maximum entry of array arr.

Beyond boolean expressions So far, all annotation has been boolean expressions, e.g. equalities, implications... How to express the following? An array arr only holds values 2. All BankCard objects have an account number greater than 0. At least one entry in the array is equal to true. The variable m holds the maximum entry of array arr. The array arr is sorted between index i and j.

Beyond boolean expressions So far, all annotation has been boolean expressions, e.g. equalities, implications... How to express the following? An array arr only holds values 2. All BankCard objects have an account number greater than 0. At least one entry in the array is equal to true. The variable m holds the maximum entry of array arr. The array arr is sorted between index i and j.

Beyond boolean expressions So far, all annotation has been boolean expressions, e.g. equalities, implications... How to express the following? An array arr only holds values 2. All BankCard objects have an account number greater than 0. At least one entry in the array is equal to true. The variable m holds the maximum entry of array arr. The array arr is sorted between index i and j. Quantifiers! x : t. A For all x of type t, A holds. forall x:t :: A x : t. A There exists some x such that A holds. exists x:t :: A

Quantifiers: Examples All BankCard objects have an account number greater than 0

Quantifiers: Examples All BankCard objects have an account number greater than 0 forall b : BankCard :: b.accno > 0; An array arr only holds only values 2

Quantifiers: Examples All BankCard objects have an account number greater than 0 forall b : BankCard :: b.accno > 0; An array arr only holds only values 2 forall i : int :: 0 <= i < arr.length ==> arr[i] <= 2; At least one entry holds the value true

Quantifiers: Examples All BankCard objects have an account number greater than 0 forall b : BankCard :: b.accno > 0; An array arr only holds only values 2 forall i : int :: 0 <= i < arr.length ==> arr[i] <= 2; At least one entry holds the value true exists i : int :: 0 <= i < arr.length && arr[i] == true;

Quantifiers and Range Predicates In this course, most common use of quantifiers in formal specification is to specify properties about arrays (or other data-structures). E.g: Only interested in integers i which are indices of an array. Range predicate: Restricts range of i more than its type (e.g. not all ints). Range Predicates forall i : int :: 0 <= i < arr.length ==> arr[i] <= 2; exists i : int :: 0 <= i < arr.length && arr[i] == true;

Today we learned Writing simple classes in Dafny Writing pre- and postconditions for methods. What an assertion is, and a little bit about how Dafny proves them. How to use quantifiers in specifications. Required Reading: Getting Started with Dafny: A Guide (link on course homepage).