Specifiche senza JML: uso delle
asserzioni
Asserzioni in Java
• Dal jdk 1.4 (da Febbraio 2002) c’è meccanismo per gestire asserzioni
• Asserzione: espressione booleana da verificare a run-time
– se espressione è vera allora si continua
– se espressione è false sistema genera errore: AssertionError, non recuperabile, e
il programma termina
• Asserzioni possono essere abilitate (o lasciate disabilitate) in fase di
compilazione (tipico: si usano durante testing, si disabilitano al rilascio):
– javac –source 1.4 Myclass.java
se codice contiene asserzioni:
– java –source 1.4 –ea Myclass.java
In sistemi safety-critical spesso le asserzioni sono lasciate abilitate anche sul
campo (ma in in modo da non causare la terminazione del programma)
• Sintassi: assert <espressione boolena>;
• Asserzioni possono essere usate ad esempio per verificare le postcondizioni
– in certi casi anche per precondizioni di metodi private, allo scopo di testing. In
Java non si usano asserzioni per le precondizioni dei metodi pubblici
2
Verifica postcondizione
• Se ensures è verificabile facilmente, si può inserire asserzione:
• static int search(int a[], int x) {
//@requires (* a <> null *)
//@ensures (*se x è presente in a ne restituisce la posizione
// altrimenti restituisce –1*)
int i;
… //qui si cerca x in a, memorizzandone posizione in i
assert(i == -1 || a[i] = =x);
return i;
}
• Es: se asserzioni abilitate e procedura trova i che non corrisponde a x 
AssertionError
• NB: in questo caso la condizione in assert è più debole della
postcondizione!
3
Dettagli per assert e AssertionError
Per avere informazioni sull’asserzione fallita, si può usare sintassi
assert Expression1 : Expression2 ;
•
•
Expression2 può essere di tipo primitivo o di tipo Object e contiene il
messaggio dettagliato mostrato dal costruttore di AssertionError quando
l’asserzione Expression1 fallisce
Esempi:
•
•
•
static int search(int a[], float x) {
… …//codice che esegue la ricerca
assert (i ==-1 || a[i] = =x) : “search(int[], float) non mantiene
postcomd.:” + i ;
return i;
}
AssertionError()
Constructs an AssertionError with no detail message.
...
AssertionError(Object detailMessage)
Constructs an AssertionError with its detail message derived from the specified
object, which is converted to a string
4
Implementare RI
il rep invariant definisce tutte le ipotesi sottostanti
all’implementazione di un tipo
– definisce quali rappresentazioni sono legali (true), cioè per quali valori
AF è definita
– deve essere verificato in tutti gli stati osservabili dagli utilizzatori
– si implementa con metodo repOk():
• Qualora non si riesca a scriverlo in un JML eseguibile è anche
possibile implementarlo in Java con un metodo ad hoc, detto
repOk():
public boolean repOk() {
// EFFECTS: restituisce true se rep invariant vale per this,
//
altrimenti restituisce false
...}
5
Esempio: repOk per IntSet
public boolean repOk() {
// c.els <> null && :
if (els == null) return false;
//for all integers i. (0 <= i < c.els.size => c.els[i] è un Integer != null) && :
for (int i = 0; i < els.size(); i++) {
Object x = els.get(i);
if (x== null || !(x instanceof Integer)) return false;
//for all integers i, j. (0 <= i< j<c.els.size => c.els[i].intValue !=c.
//els[i].intValue:
for (int j = i+1; j< els.size(); j++)
if (x.equals(els.get(j))) return false;
}
return true;
}
6
Come verificare RI con repOk
1. Nel codice: inserire il controllo di repOk nei mutators e nei
costruttori, tramite il meccanismo delle asserzioni
•
•
Si chiama assert repOk(); al termine del metodo o del costruttore: se
risultato è true si continua, altrimenti AssertionError
Molto utile (ma codice più lento!). Esempio per IntSet:
public void insert(int x) {
… …//codice che inserisce in this.els
assert repOk();
return;}
Se repOk() non è verificato, viene generato errore:
AssertionError in function IntSet.insert(int)
•
NB: per usare assert si deve compilare in Java con la
direttiva apposita
7
Esempio di verifica di repOk() e di
ensures
public void insert(int x) {
//@ensures this.isIn(x) && (*this include gli elementi in \old(this)*)
…//codice che inserisce in this.els
assert repOk() : “insert(int) non mantiene RI:”+ x;
assert isIn(x) : this+ “insert (int) non mantiene postcond:”
+ x;
return;
}
8
Scarica

asserzioni