Specifiche senza JML: uso delle asserzioni
2 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 ; 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
3 Verifica postcondizione Se ensures è verificabile facilmente, si può inserire asserzione: static int search(int a[], int x) { (* a <> null *) (*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!
4 Dettagli per assert e AssertionError Per avere informazioni sullasserzione fallita, si può usare sintassi assert Expression 1 : Expression 2 ; Expression2 può essere di tipo primitivo o di tipo Object e contiene il messaggio dettagliato mostrato dal costruttore di AssertionError quando lasserzione 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
5 Implementare RI il rep invariant definisce tutte le ipotesi sottostanti allimplementazione 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...}
6 Esempio: repOk per IntSet public boolean repOk() { // c.els <> null && : if (els == null) return false; // for all integers i. (0 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 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; }
7 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
8 Esempio di verifica di repOk() e di ensures public void insert(int x) { 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; }