Contract-based Programming: a Route to Finding Bugs Earlier

Similar documents
Contract-based Programming in Ada 2012 A Tutorial

Definition: Data Type A data type is a collection of values and the definition of one or more operations on those values.

Data Types. 9. Types. a collection of values and the definition of one or more operations that can be performed on those values

Hybrid Verification in SPARK 2014: Combining Formal Methods with Testing

Spark verification features

High Performance Computing

Chapter 9 Technicalities: Classes, etc. Walter C. Daugherity Lawrence Pete Petersen Bjarne Stroustrup Fall 2007

Chapter 9 Technicalities: Classes, etc.

History. used in early Mac development notable systems in Pascal Skype TeX embedded systems

CS113: Lecture 3. Topics: Variables. Data types. Arithmetic and Bitwise Operators. Order of Evaluation

Flashback Technicalities: Classes, etc. Lecture 11 Hartmut Kaiser

Chapter 9 Technicalities: Classes

Parallel and Concurrent Programming

Chapter 9 Technicalities: Classes, etc.

Types, Operators and Expressions

Types, Operators and Expressions

File Handling in C. EECS 2031 Fall October 27, 2014

Demand Estimation Sub Committee Ad-hoc Work Plan

Questions? Static Semantics. Static Semantics. Static Semantics. Next week on Wednesday (5 th of October) no

Excel Functions & Tables

Outline. software testing: search bugs black-box and white-box testing static and dynamic testing

Practice with variables and types

CS Programming I: Arrays

Programming for Engineers Structures, Unions

Ada 2012, SPARK 2014, and Combining Proof and Test!

CSC Advanced Object Oriented Programming, Spring Specification

3. EXCEL FORMULAS & TABLES

Announcements. Problem Set 3 is due this Tuesday! Midterm graded and will be returned on Friday during tutorial (average 60%)

EECS2301. Example. Testing 3/22/2017. Linux/Unix Part 3. for SCRIPT in /path/to/scripts/dir/* do if [ -f $SCRIPT -a -x $SCRIPT ] then $SCRIPT fi done

Chapter 9 Technicalities: Classes, etc.

This report is based on sampled data. Jun 1 Jul 6 Aug 10 Sep 14 Oct 19 Nov 23 Dec 28 Feb 1 Mar 8 Apr 12 May 17 Ju

More Binary Search Trees AVL Trees. CS300 Data Structures (Fall 2013)

Withdrawal of Text Processing (Business Professional)

Practice with variables and types

More BSTs & AVL Trees bstdelete

Undergraduate Admission File

Scientific Programming in C X. More features & Fortran interface

Principles of Programming Languages

520 Principles of Programming Languages. Arithmetic. Variable Declarations. 19: Pascal

Stepwise Refinement. Lecture 12 COP 3014 Spring February 2, 2017

Introduction to Fortran

CMIS 102 Hands-On Lab

Section 1.2: What is a Function? y = 4x

CSE 341 Section Handout #6 Cheat Sheet

How It All Stacks Up - or - Bar Charts with Plotly. ISC1057 Janet Peterson and John Burkardt Computational Thinking Fall Semester 2016

Different kinds of resources provided by a package

COURSE LISTING. Courses Listed. Training for Database & Technology with Modeling in SAP HANA. 20 November 2017 (12:10 GMT) Beginner.

ECSE 321 Assignment 2

A class is a user-defined type. It is composed of built-in types, other user-defined types and

Programming Data Structures and Algorithms Prof. Shankar Balachandran Department of Computer Science Indian Institute of Technology, Madras

Freedom of Information Act 2000 reference number RFI

HPE Security Data Security. HPE SecureData. Product Lifecycle Status. End of Support Dates. Date: April 20, 2017 Version:

Markets Gateway Roadmap

software.sci.utah.edu (Select Visitors)

Operator overloading: extra examples

Hardware versus software

ICT PROFESSIONAL MICROSOFT OFFICE SCHEDULE MIDRAND

Assertions. Assertions - Example

COURSE LISTING. Courses Listed. with SAP Hybris Marketing Cloud. 24 January 2018 (23:53 GMT) HY760 - SAP Hybris Marketing Cloud

Programming languages Ada

Oxford Scientific Software Ltd

Data Types H&K Chapter 7. Instructor - Andrew S. O Fallon CptS 121 (October 17, 2018) Washington State University

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

Testing, Debugging, and Verification

NCC Cable System Order

OCaml Style Guide Fall 2017

10 Key Things Your VoIP Firewall Should Do. When voice joins applications and data on your network

Type Definition. C Types. Derived. Function Array Pointer Structure Union Enumerated. EE 1910 Winter 2017/18

Last time. Reasoning about programs. Coming up. Project Final Presentations. This Thursday, Nov 30: 4 th in-class exercise

Reasoning about programs

UC DAVIS THERMAL ENERGY STORAGE (TES) TANK OPTIMIZATION INVESTIGATION MATTHEW KALLERUD, DANNY NIP, MIANFENG ZHANG TTP289A JUNE 2012

Foundations, Reasoning About Algorithms, and Design By Contract CMPSC 122

SME License Order Working Group Update - Webinar #3 Call in number:

Lecture Notes on Contracts

If Case Loop Next Exit

Project 1 System Calls

QUIZ. Can you find 5 errors in this code?

BANGLADESH UNIVERSITY OF PROFESSIONALS ACADEMIC CALENDAR FOR MPhil AND PHD PROGRAM 2014 (4 TH BATCH) PART I (COURSE WORK)

Type Hierarchy. Comp-303 : Programming Techniques Lecture 9. Alexandre Denault Computer Science McGill University Winter 2004

Asks for clarification of whether a GOP must communicate to a TOP that a generator is in manual mode (no AVR) during start up or shut down.

Assertions, pre/postconditions

Strings, Lists, and Sequences

QUIZ. What is wrong with this code that uses default arguments?

Getting in Gear with the Service Catalog

Functions and Recursion

Topics. Software Testing Test Driven Development Black Box Testing Unit Testing White Box Testing Coverage Testing Software Debugging

CS1100 Introduction to Programming

Unit Testing as Hypothesis Testing

P1 Engineering Computation

Programming languages Ada

Functional Testing (Black Box Testing)

} Evaluate the following expressions: 1. int x = 5 / 2 + 2; 2. int x = / 2; 3. int x = 5 / ; 4. double x = 5 / 2.

MIND THE GOOGLE! Understanding the impact of the. Google Knowledge Graph. on your shopping center website.

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

COS 320. Compiling Techniques

What future changes are planned to improve the performance and reliability of the Wairarapa Connection?

Our First Programs. Programs. Hello World 10/7/2013

What you learned so far. Loops & Arrays efficiency for statements while statements. Assignment Plan. Required Reading. Objective 2/3/2018

C-Programming. CSC209: Software Tools and Systems Programming. Paul Vrbik. University of Toronto Mississauga

Static verification of program running time

Transcription:

Contract-based Programming: a Route to Finding Bugs Earlier JSA Research & Innovation February 2018

Subprogram Contracts Type Contracts Contract-based Programming A software development technique, used to find programming errors earlier in the development process. In its strictest form, the contracts are checked as a part of the compilation process, and only a program which can be proven to conform with the contracts will compile 1. In a less strict form, it is more similar to preventive debugging, where the contracts are inserted as run-time checks, which makes it more likely to identify errors during testing. In this presentation I will focus on preventive debugging, i.e. how you can insert assertions efficiently in your source text. 1 This is what SPARK 2014 does. Stay for the following presentation, if you find it interesting.

Subprogram Contracts Type Contracts Contract-based Programming You insert assertions in your source text to tell all readers of the source text both humans, compilers and other tools something concrete about the execution state of the software. Notice that assertions are different from comments, since the compiler understands them, and can both check that they are correct, and use them for optimising the generated code.

Subprogram Contracts Type Contracts Assertions It is unfortunately common to disable run-time checking of unproven assertions in production code, and only have the run-time checking enabled during testing. In my view that is like bringing along the life-vests during testing of a ship, but removing them before going to sea for real, so... Don t do that! If run-time checking of a specific assertion is too costly for the timing requirements of your application, prove that the assertion is correct. Once the assertion has been proven true, it is safe to disable checking of it at run-time.

Subprogram Contracts Type Contracts Subprogram Contracts: Pre- and Post-conditions The typical view of contract-based programming is that its core is pre- and post-conditions of subprograms (functions, procedures, etc.) Here is an example: procedure Increment (Counter : in out Natural; Step : in Positive) with Pre => (Counter < Natural Last) and (Step <= Natural Last - Counter), Post => (Counter > 0);

Subprogram Contracts Type Contracts Subprogram Contracts: Pre- and Post-conditions You could achieve the same run-time effect with plain old-fashioned assertions in the body of the subprogram: procedure Increment (Counter : in out Integer; Step : in Integer) is begin pragma Assert (0 <= Counter); -- Natural pragma Assert (1 <= Step); -- Positive pragma Assert ((Counter < Integer Last) and (Step <= Natural Last - Counter)); Counter := Counter + Step; pragma Assert (Counter > 0); end Increment;

Subprogram Contracts Type Contracts Subprogram Contracts: Pre- and Post-conditions Having the assertions in the specification does give us some benefits: You can write them when you specify the subprogram. This is a benefit for us humans. They are visible to the user of the subprogram. This is a benefit for us humans. They are explicitly a part of the interface between the subprogram and its users. This is a benefit for static analysis tools. But none of these benefits can easily be shown to really scale to a significant difference in development effort.

Subprogram Contracts Type Contracts Type Contracts When you put contracts on your types, you get a nice scaling benefit, as you write the contract once, but the compiler automatically inserts checks of the contract (assertions) everywhere you modify variables of the type in a way that might break the contract. If your compiler is good, it will try to prove these automatically inserted assertions at compile-time, and only keep those it can t prove.

Subprogram Contracts Type Contracts Type Contracts: Ranges The simplest kind of type contracts in Ada is the range: subtype Natural is Integer range 0.. Integer Last; subtype Positive is Integer range 1.. Integer Last; You can declare ranges of numeric types and enumeration types: subtype Non_Negative_Float is Float range 0.0.. Float Last; type Months is (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec); subtype Winter is Months range May.. Oct;

Subprogram Contracts Type Contracts Type Contracts: Static Predicates The next step up in complexity is the static predicate: subtype Summer is Months with Static_Predicate => Summer in Nov.. Dec Jan.. Apr; This allows you to put constraints formulated as static set conditions on your subtypes.

Subprogram Contracts Type Contracts Type Contracts: Dynamic Predicates The most advanced form of type contract in Ada exists in two forms. One is the public dynamic predicate: subtype Prime is Integer range 2.. Integer Last with Dynamic_Predicate => (for all N in 2.. Prime - 1 => Prime mod N /= 0); Any kind of Boolean expression is allowed in a dynamic predicate. You can even use one which changes with time: subtype Past_Time is Ada.Calendar.Time with Dynamic_Predicate => Past_Time < Clock; subtype Last_Hour is Past_Time with Dynamic_Predicate => Clock - 3600.0 <= Last_Hour;

Subprogram Contracts Type Contracts Type Contracts: Type Invariants For private types with internal constraints, you use a type invariant: package Places is type Disc_Point is private; -- various operations on disc points private type Disc_Point is record X, Y : Float range -1.0.. +1.0; end record with Type_Invariant => Disc_Point.X ** 2 + Disc_Point.Y ** 2 <= 1.0; end Places; Adapted from the Ada 2012 Rationale.

I advise that you work on your contracts in this order: 1 Specify types. 2 Specify subprograms. 3 Adapt the subprogram specifications based on use cases for your package/library.

Make sure your type declarations are as detailed as possible. Declaring a new type or a subtype depends on what level of inter-type compatibility you want and of course if there is a type to derive from. Put an appropriate constraint on the range of values the (sub)type can have. Add any extra constraints as predicates (non-private types) or type invariants (private types). The simpler a kind of contract you use to declare the type, the more things you can use it for.

: Refining a Contract Primes are integers: subtype Prime is Integer;... larger than 1: subtype Prime is Integer range 2.. Integer Last;... and have no other factors than 1 and the prime itself: subtype Prime is Integer range 2.. Integer Last with Dynamic_Predicate => (for all N in 2.. Prime - 1 => Prime mod N /= 0);

: Contract Kinds and Usage Subtypes of discrete types declared with ranges can be used as array indices, while those declared with predicates or type invariants can t. So when we declare the subtype Positive like this: subtype Positive is Integer range 1.. Integer Last;... then we can declare the array type String like this: type String is array (Positive range <>) of Character;

: Contract Kinds and Usage Subtypes declared with ranges or static predicates can be used in case statements, while those declared with dynamic predicates or type invariants can t. So when we declare the seasons like this: subtype Spring is Months range Mar.. May; subtype Summer is Months range Jun.. Aug; subtype Autumn is Months range Sep.. Nov; subtype Winter is Months with Static_Predicate => Winter in Dec Jan Feb;

: Contract Kinds and Usage... then we can use the seasons in a case statement like this: case Input is when Spring => Put_Line ("Light and warmer weather."); when Summer => Put_Line ("Vacation and strawberries."); when Autumn => Put_Line ("Wind and falling leaves."); when Winter => Put_Line ("Snow - we hope."); end case;

Make sure that you declare the arguments for your subprograms as specifically as possible. Select the proper direction ( in, out or in out ) for each of the arguments to a subprogram. Select as specific a (sub)type as possible for each of the arguments to a subprogram. Use pre-conditions (post-conditions) to declare stronger constraints on the input (output) values than those implied by the selected subtypes.

: Refining a Specification We want to be able to increment a counter by arbitrary steps. We use ( in ) the value of both the counter and the step size to generate ( out ) a new value for the counter: procedure Increment (Counter : in out Integer; Step : in Integer); We count from zero and up (natural numbers). An increment is by one or more (positive numbers): procedure Increment (Counter : in out Natural; Step : in Positive);

: Refining a Specification There is an upper limit (Natural Last) to how far we can count with our selected type: procedure Increment (Counter : in out Natural; Step : in Positive) with Pre => (Counter < Natural Last) and Once Increment returns Counter has changed: procedure Increment (Counter : in out Natural; Step : in Positive) with Pre => (Counter < Natural Last) and (Step <= Natural Last - Counter), Post => (Counter > 0);

: Refining a Specification What are the requirements of your subprograms? Do some of your subprograms have some special requirements, which should be met before they can be called? Can a subprogram only be called once? Can a subprogram only be called when the system is in a specific state? This can be documented with appropriately formulated pre-conditions to the subprograms.

: Refining a Specification If we want to write to a file, it should be open and writable: procedure Put (File : in File_Type; Item : in String) with Pre => (Is_Open (File)) and then (Mode (File) in Out_File Append_File); Initialise only once: procedure Initialise with Pre => State = Not_Initialised;

: Ideal Pre- and Post-conditions In my view, the ideal pre- and post-conditions are simply A_Formal_Parameter in A_Subtype, but there are cases such as the example on the preceding slide where the contracts necessarily have to be more complex than that.

Ada doesn t allow you to write contracts packages as such. It still make sense to take a broader view of the all the contracts in a package. If one specifies contracts one subprogram at a time, one may miss contract details on one subprogram, which would be helpful for another subprogram. The following slides contain a few guidelines for ensuring consistent pre- and post-conditions for entire packages.

: Aligning Pre- and Post-conditions Do post- and pre-conditions match for likely sequences of calls to the declared subprograms? 1 Identify use cases for the package (sequences of subprogram calls). 2 For each call in a use case: a Verify that the documented state of the input data matches constraints and pre-conditions for the called subprogram. b If there is a mismatch: Attempt to narrow down the documented, possible output values of the source of the input data (by changing constraints and post-conditions). c Identify the documented state of the modified parameters after the call.

: Aligning Pre- and Post-conditions We look at a simple Text I/O package with some contracts added: procedure Open (File : in out File_Type; Mode : in File_Mode; Name : in String); procedure Close (File : in out File_Type); procedure Put_Line (File : in File_Type; Item : in String) with Pre => (Is_Open (File)) and then (Mode (File) in Out_File Append_File), Post => (Line (File) = Line (File) Old + 1);

: Aligning Pre- and Post-conditions 1 A use case: Open (File => Target, Name => "output.txt", Mode => Out_File); Put_Line (File => Target, Item => "Hello."); Close (File => Target); 2 Open: a File, Name and Mode all OK. No pre-conditions. b (no mismatch) c Target can have any valid File_Type value.

: Aligning Pre- and Post-conditions 2 Put_Line: a Pre-conditions on File not matched by the documented constraints on Target. Item OK. b Target was last modified by Open, so we add some appropriate post-conditions there: procedure Open (File : in out File_Type; Mode : in File_Mode; Name : in String) with Post => (Is_Open (File) and Text_IO.Mode (File) = Mode); c We now know that Target is open and has the mode Out_File.

: Aligning Pre- and Post-conditions 2 Close: a Close has no pre-conditions, so Target matches the documented requirements for the formal parameter File. b (no mismatch) c We know that Target has been changed, so it can have any valid File_Type value. As some of you may have noticed, I have omitted to document that it is an error to open a file which already is open, or to close one which already is closed. This is left as an exercise.

Don t disable unproven assertions. It is possible to write your assertions centralised, and then have the compiler insert them where it can t prove that they are not violated. Don t use more advanced contract notations than required by your problem. Use use cases for your packages to check if your contracts are complete.

Contact information JSA Research & Innovation jacob@jacob-sparre.dk http://www.jacob-sparre.dk/ Examples: http://www.jacob-sparre.dk/programming/ contracts/fosdem-2018-examples.zip