35
S Asserting Expectations

Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Embed Size (px)

Citation preview

Page 1: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

S

Asserting Expectations

Page 2: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Introduction

-Observation alone is not enough for debugging as it can be a burden for a programmer.

-One must compare observed facts with expected program behavior.

-This can take multitudes of time which can also be expensive.

Page 3: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Observation vs. Assertion

-With computing power increasing exponentially, it has become reasonable to shift the burden of observing code over to the computer.

-That is, to have the computer check whether the program state is still sane, or whether and infection has occurred.

Page 4: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Observation vs. Assertion

The above image shows the difference between observation and assertion in relation to time. Observation(a) is limited to small probes while assertion(b) can cover a much larger area over time.

Page 5: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Basic Assertions

-To have a program ensure it’s sane state automatically is actually quite simple.

-Inserting code that checks for infections is a simple yet meaningful task that can save large amounts of time and help further develop efficient code.

Page 6: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Basic Assertions

-For instance, to ensure that a divisor is nonzero one could write:

-This type of code has been used since the dawn of computing but it is still somewhat clumsy.

Page 7: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Basic Assertions

-The assert(x) function is a better alternative that aborts is the execution of x should be false. A simple assert function is shown below.

Page 8: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Assertion and Macros

-In practice, simply having assertions marked as such does not suffice.

-We want to be able to turn assertions off, and we want them to report diagnostic information about the specific even that failed.

Page 9: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Asserting Invariants

-The most important use of assertions in debugging is to ensure data invariants –properties that must hold throughout the entire execution.

-With each invariant we must set pre/post conditions and then test them later for correctness.

Page 10: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Ensuring Sanity

-The boolean sane() method can be used to ensure a sane state during execution. Using this function helps eliminate the redundancy of many individual assert() statements.

Page 11: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Sane() Example

-The following statement ensures that Time will be a valid time between 00:00:00 and 23:59:60.

Page 12: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Locating Infections

-Pre-conditions: if violated, infection must have taken place before invariant executed.

-Post-conditions: if violated infection must have taken place during invariant execution.

All assertion pass :if the post condition holds, the infection cannon have taken place during invariant execution.

Page 13: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Complex Invariants

-If data structures get more complex, the invariants become more complex too but also ensure more properties.

-The next slide is an example of a class invariant of a JAVA red/black tree – the base of JAVA TreeMap class.

Page 14: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Complex Invariant Example

Page 15: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Invariant in Debuggers

-Once one has a function that checks data invariants, one can also invoke it in an interactive debugger to check data sanity on-the-fly. A conditional breakpoint in GDB such as:

Acts like an assertion.

Page 16: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Design by Contract Concept

The EIFFEL language incorporates the concept of design by contract, where a contract is a set of preconditions that must be met by the caller and a set of post conditions that are guaranteed by the callee.

Page 17: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Design by Contract Concept

- In EIFFEL, a contract regarding set_hour() would be specified as:

- In addition require and ensure, EIFFEL provides an invariant keyword the condition of which is checked before and after every invocation of the public method.

Page 18: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Defining Invariants with Z

- Z is a specification language built upon the concepts of discrete math.

- In Z specification, it is easy to recognize the invariants as well as the pre and post conditions.

- Such a specification is obviously far more precise than the natural-language version.

Page 19: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Invariants with Z Example

Page 20: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Java Modeling Language (JML)

-JML is a modeling language that excels in expressive power, quantity, and quality.

-JML assertions are written as special comments in the JAVA code, recognized by JML tools alone and ignored by ordinary JAVA compilers.

-Using requires and ensures keywords, one can specify the pre and post conditions of an individual JAVA method in EIFFEL style.

Page 21: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

JML Example

Page 22: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

JML

-invariant is used to assert data sanity (as in EIFFEL, the invariant is checked before and after invocation of a public method).

-\forall is used to express conditions that span multiple variables

-signals is the specification of exceptional behavior

Page 23: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

More Complex JML

Page 24: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Relative Assertions

-Sometimes it is beneficial to compare two programs that are expected to have similar behavior in some aspect or possibly every aspect.

-One common scenario is if P1 is a new version of P0.

-One can simply compare the results of the reference program to the program being tested.

Page 25: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Compare Variable Across Two Runs

Page 26: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

MALLOC_CHECK

-Using the GNU C runtime library, one can avoid common errors related to heap use simply by setting an environment variable called MALLOC_CHECK.

-For example, one can detect multiple deallocation of heap memory.

Page 27: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

MALLOC_CHECK Example

Page 28: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

ELECTRICFENCE

-The ELECTRICFENCE library effectively prohibits buffer overflows.

-Arrays in memory are allocated such that each array is preceded and followed by a nonexisting memory area.

Page 29: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

VALGRIND

-VALGRIND provides the functionality of ELECTRICFENCE, plus a little more. VALGRIND detects:

-Read access to noninitialized memory

-write or read access to nonallocated memory

-write or read access across array boundaries

-write or read access in specific stack areas

-Detection of memory leaks

Page 30: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

VALGRIND Example

Page 31: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Language Extensions: CYCLONE

-There exists safer dialect’s of existing programming languages that carry extensions that allow programmers to specify further properties of language entities.

-One example is CYCLONE which is a safer dialect of the C programming language.

Page 32: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

CYCLONE

-CYCLONE’s central extension of C is the concept of special pointers.

-For instance, in CYCLONE one can declare a pointer that can never be NULL by using @ instead of *.

-Another feature is fat pointers – pointers that not only record a location but bound information (such as the size of the area being pointed to).

-Fat pointers are declared using ? Instead of *.

Page 33: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Assertion and Production Code

-When it comes to releasing the program, should we still have checks enabled? Depends.

Page 34: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Assertion and Production Code

-Critical Results: If your program computes a result that people’s lives, health or money depends on, it is a good idea to validate the result using some additional computation.

-External Conditions: Any conditions that are not within our control must be checked for integrity.

-The more active assertions there are, the greater the chances of catching infections.

-The sooner a program fails, the easier it is to track the defect.

-Defects that escape into the field are the most difficult to track.

-By default, failing assertions are not user friendly.

-Assertions impact performance

Page 35: Asserting Expectations. Introduction -Observation alone is not enough for debugging as it can be a burden for a programmer. -One must compare observed

Tools-JML: http://www.jmlspecs.org/.

-ESC/JAVA: combines static checking with JML

-GUARD: the GUARD relative debugger was presented by Sosic and Abramson, who also pioneered the concept of relative debugging.

-VALGRIND: The VALGRIND tool for Linux is part of Linux distributions for x86 processors

-PURIFY: PURIFY, marketed by IBM, is also available for Linux/Unix and Windows.

-INSURE++: INSURE++ is a commercial tool that detects memory problems by instrumenting C and C++ source code.

-CYCLONE: dialect was developed by jim et al. An open-source compiler for Linux can be downloaded.

-CCURED: The CCURED language by Necuala et al. Takes an approach similar to that of CYCLONE, but moves control from the programmer to the system