Técnicas Avanzadas de Testing Automatizado

Anuncio
Técnicas Avanzadas de
Testing Automatizado
Generación basada en Constraint Solving
(SAT Solving)
SAT-Solving
El problema de satisfactibilidad booleana es el
siguiente: dada una fórmula proposicional A, encontrar
una asignación de valores de verdad para las variables
v : Vars(A) ! {T, F}
que haga a A verdadera
Primer problema en demostrarse NP-completo.
Existen varios SAT solvers basados en el algoritmo de
Davis-Putnam-Logemann-Loveland algorithm (1960,
1962).
El Lenguaje de Modelado
Alloy (Jackson, MIT)
Permite describir dominios de datos, y
operaciones sobre los dominios
La herramienta Alloy Analyzer permitea analizar si
ciertas propiedades se cumplen en los modelos
(pero dentro de cotas para los dominios de datos).
Los modelos se traducen a fórmulas
proposicionales, y se usa un SAT solver para
buscar contraejemplos.
Alloy: Ejemplo
sig Data { }
one sig Null { }
sig Node {
val: Data,
next: Node+Null
}
sig List {
head: Node+Null
}
definiciones de dominios y
su estructura
Las operaciones se
pueden definir con
predicados
restricciones sobre
la especificación
(propiedades supuestas)
fact AcyclicLists {
all l: List, n: Node | n in l.head.(*next) => n !in n.(^next)
}
propiedades a ser
chequeadas
assert NextIsInjective {
all l: List, n1, n2: Node | n1+n2 in l.head.*next and n1 != n2 => n1.next != n2.next
}
Expresiones en Alloy
Tanto las signaturas como los campos de las signaturas definen relaciones. Por ejemplo,
Node define una relación unaria, y next define una relación binaria entre Node y Node u
{Null}.
Tenemos algunas constantes relacionales:
•
none (rel. vacía), univ (relación unaria universal) e iden (relación identidad sobre el
universo)
Varias operaciones pueden aplicarse a relaciones:
•
unión (+), intersección (&), diferencia (-) y producto cartesiano (->)
•
composición (.)
•
conversa (~)
•
overriding (r++s = (r - (dom[s]->univ)) + s)
•
clausura transitiva (^r) y reflexo-transitiva(*r)
Fórmulas en Alloy
Usando las expresiones relacionales, podemos construir fórmulas:
•
inclusión relacional (r in s)
•
igualdad relacional (r = s)
•
vacuidad relacional (no r)
•
conjunción (f1 and f2), disyunción (f1 or f2), negación (not f1) e implicación (f1 => f2)
de fórmulas
•
cuantificación universal (all x: D | f1)
•
cuantificación existencial (some x: D | f1)
En Alloy, toda expresión denota una relación. Los elementos se caracterizan mediante
singletons (relaciones unarias con un único elemento)
Alloy Analyzer
sat?
Alloy spec
aserción
spec and (not aserción)
contraejemplo
unsat?
propiedad válida
dentro de las cotas provistas
ZChaff
SAT4J
Berkmin
MiniSAT
cotas para
dominios
The Alloy Analyzer
Alloy Model
Alloy Analyzer
KodKod
model
KodKod
Propositional
formula in
CNF
SAT-Solver
UNSAT or
counterexample
KodKod (Torlak, Jackson)
Para cada símbolo relacional R, existen cotas inferior y
superior: lR y uR.
Si una tupla t pertenece a lR, entonces t debe ocurrir en
toda interpretación de R.
Si t no pertenece a uR, entonces t no puede ocurrir en
ninguna interpretación de R.
KodKod
Intuitivamente,
KodKod: De Relaciones a
Proposiciones
Sean R y S relaciones binarias sobre un conjunto A.
variables
Sea 3 la cota de A. Luego:
proposicionales
⇥
⇥
s11 s12 s13
r11 r12 r13
⇤ r21 r22 r23 ⌅ S
⇤ s21 s22 s23 ⌅
R
r31 r32 r33
s31 s32 s33
rij es una variable proposicional que modela el
hecho de que (i,j) está en R. Lo mismo para sij.
KodKod: De Relaciones a
Proposiciones
Para la conversa, tenemos:
Los
términos
s11 s21 s31
relacionales
son mapeados
⇤
s
s
s
S̆
12
22
32
a matrices de
s13 s23 s33
fórmulas
proposicionales
For join (union), we have:
R + S̆
r11
⇤ r21
r31
s11
s12
s13
r12
r22
r32
s21
s22
s23
⇥
⌅
r13
r23
r33
⇥
s31
s32 ⌅
s33
KodKod: De Relaciones a
Proposiciones
Para igualdades entre términos:
R + S̆ = T
r11
⇤ r21
r31
s11
s12
s13
(r11 ⇤ s11
r12
r22
r32
Se extiende a
conectivos⇥y
t11
s21cuantificadores
r13 s31
s22 r23 s32 ⌅ = ⇤ t21
t31
s23 r33 s33
t11 ) ⇥ (r12 ⇤ s21
t12 ) ⇥ (r13 ⇤ s31
t12
t22
t32
⇥
t13
t23 ⌅
t33
t13 ) ⇥ . . .
DynAlloy: Extendiendo Alloy con
Acciones
• Extensión de Alloy, para describir de mejor manera el
cambio de estado y las ejecuciones
• provee notación para acciones atómicas, definidas en
términos de pre- y post-condiciones
• provee operadores para formar acciones compuestas
(programas)
• las aserciones para programas pueden darse en términos
de aserciones de corrección parcial
DynAlloy: Una Especificación de
Ejemplo
act Head(l: List, d: Data)
pre = { l.head != Null}
post = { d’ = (l.head).val }
acciones definidas por pre- y
post-condiciones
act Tail(l: List)
pre = { l.head != Null}
post = { l’.head = (l.head).next }
assertPartialCorrectness {
pre = { l.head != Null and noCycles(l.head) }
program = { Tail(l) ; (Head(l,d) + Tail(l))* }
post = { noCycles(l’.head) }
}
propiedades sobre
ejecuciones, a ser
chequeadas
Análisis de Especificaciones DynAlloy
Alloy Analyzer
cotas para dominios
DynAlloy spec
{pre} P {post}
cotas para
iteraciones
spec and (pre and
not(bwlp(P,post,k)))
bwlp(P, post, k)
sat?
contraejemplo
unsat?
propiedad válida dentro
de las cotas establecidas
Cómputo de bwlp
• Operadores:
• acciones atómicas: {pre} a {post}
• test: pred?
• elección no determinista: p1+p2
• composición secuencial: p1; p2
• iteración: p* (= p + p;p + p;p;p + ...)
Un Ejemplo Simple
module example1
open util/integer
pred equ[l,r: univ] { l=r }
action Inc[x: Int] {
pre { gte[x,0] }
post { equ[x',add[x,1]]}
}
action Dec[x: Int] {
pre { gt[x,0] }
post { equ[x',sub[x,1]]}
}
assertCorrectness always_gt_zero[y: Int] {
pre = { equ[y,0] }
program = {
Inc[y];
Inc[y];
Inc[y];
Dec[y];
Dec[y]
}
post = { gt[y',0] }
}
check always_gt_zero
Análisis Automático de
Código Java (con DynAlloy)
Se mapea la jerarquía de clases Java a una
jerarquía de signaturas Alloy.
Se mapean las sentencias atómicas Java a
acciones atómicas DynAlloy.
Se mapea programas Java a programas DynAlloy.
jects, and atomic actions that modify an object’s field. We
ing class fields modified
denote
ObjectsC
the unary
relation (set) that contains
is used
Dyn
parameters
of by
thethe
DynA
2.2 Aby
Brief
Introduction
To DynAlloy
the DynAlloy
mo
the set of objects from class C that are part of the heap at a
tion applies
to class con
DynAlloy
is an This
extension
ofbe
Alloy
conceived
foreffect
modeling
associated
given
point[10]
in time.
set can
modified
by the
of andparameter
this isAlloy
remov
analyzing
actions
specified
through
pre
and
post-conditions
written
the
form of cod
an action.
The
translation
in Alloy. From these atomic actions, new, more complex actions,
In order to handle creation of objects of class C in DynAlin two steps.
We first tra
run program
fo
can be constructed using action combinators. If
loy, we introduce an atomic action called NewC, specified as
code, and then translate
the Alloy Analyze
A[x1:T1,...,xn:Tn]
follows:
code. The techniques b
Notice
that the set ObjectsC should have been passed as a
Normalized
Java code
and NewC[o
worth emphasizin
act
: C]
parameter.B[x1:T1,...,xn:Tn,y1:T1,...,yn:Tn]
In order to maintain notation simple, we keep this •
models isand
partial,
pre = { true }
constructor
meth
state
variable
global.
sizesofofprimitive
data dom
are Alloy
an atomic
actionand
“atomic”
declared through literals
post formulas,
= {o’ !in
ObjectsC
o’ in isObjectsC’}
ty
* (iteration) opera
An atomic action that sets the value of field “f” of object
a triple
Java a DynAlloy: Acciones
Atómicas
bles for
oughly
f being
asserts,
] asser-
{
}
satisfy
satisfy
“o”, is described in DynAlloy as follows:
act atomic[x1:T1,...,xn:Tn]
= { A[x1,...,xn]
actpre
Setf[o
: C, v : C’,} f : C -> C’]
post
}
pre == {{ oB[x1,...,xn,x1’,...,xn’]
in ObjectsC }
post =variable
{ f’ x=i fin++
->condition
v) } refers to the value
Primed
the(o
post
of variable xi upon action termination. As an example, action
From the class extension hierarchy in Java, a signature exvarAssign below models assignment of a value to a variable:
tension hierarchy is readily defined in DynAlloy. Translation
act
VarAssign[v1,
: C]
(seAabrevia
v1 := v2)
of
a class
to DynAlloyv2
is immediate.
class declaration
pre = { true }
class
postC ={ { v1’ = v2 }
C1this
field1;
Since
atomic action is used often, we will use the more pro... notation v1 := v2. Actions denote state (variable valgrammatic
Ck fieldk;
uations)
transitions. Atomic actions relate those pairs of valuations
2.3 The Transl
Let us consider th
and singly linked
public class LN
LNode next;
int key;
}
public class Li
/*@
@ invariant
@
\reach(t
@
!\reach(
@*/
nted,
nts.
is a
n e1
nts.
riate
code
nted,
riate
hink
data
nts.
hink
data
t e1
riate
We
t e1
hink
We
data
tt pae1
rim-
of
non-void
return
type. an
According
to (1), the result.
translation
of
whose
header
includes
(ouput) parameter
In the
v.f =
-->of DynAlloy action m
method
m e1.m(p1,...,pk)
guarantees
existence
translation
of
the body the
of m,
we translate
p1,...,
pk] ;parameter
Setf[v,result.
r, f].
whose m[r,
headere1,
includes
an (ouput)
In the
return e
-->
VarAssign[result, e].
translation
of the bodyofofthe
m,form
we translate
Return statements
“return e” (where e is an
For more must
complex
program
constructs,
the
translation
is
expression),
occur
in
the
body
of
a
Java
method
m
return e
-->
VarAssign[result, e].
defined
as follows:
of
non-void
return type. According to (1), the translation of
For more complex program constructs, the translation is
method
m guarantees
the existence
of DynAlloy
action m
while
(pred)
{stmt}
⇥
⇤
(pred?;
stmt);
(!pred)?,
definedheader
as follows:
whose
parameter
result. In the
stmt1 ; stmt2 includes an (ouput)
⇤⇥ stmt1;
stmt2,
translation
of the
body
of m, ⇤⇥
we translate
while
(pred)
{stmt}
(pred?;stmt1)
stmt);+
(!pred)?,
if (pred)
stmt1
else
stmt2
(pred?;
((!pred)?;
stmt2) ,
stmt1 ; stmt2
⇤⇥ stmt1;
stmt2,
return
e
-->
VarAssign[result,
e].
if (pred) stmt1 else stmt2 ⇤⇥ (pred?; stmt1) +
For the
more
complex
program
translation
is
where
boldface
stmt,
stmt1constructs,
and((!pred)?;
stmt2the
stand
for the, restmt2)
defined
follows: of the translation to the statements stmt,
cursive as
application
stmt1 and
stmt2, respectively.
Predicates
are translated
to Alwhere
the
boldface
stmt,
stmt1
and
stmt2
stand
for
the
rewhile (pred) {stmt}
⇤⇥
(pred?; stmt); (!pred)?,
loy formulas
using the
translation
to be
in Section
cursive
of the
translation
to presented
thestmt2,
statements
stmt,
stmt1 ;application
stmt2
⇤⇥ stmt1;
2.2. and stmt2, respectively. Predicates are translated to Alstmt1
if (pred) stmt1 else stmt2 ⇤⇥ (pred?; stmt1) +
loy formulas using the translation to ((!pred)?;
be presented
in Section
stmt2)
,
2.2 Translating Annotations to Alloy
2.2.
In thisthe
section
we describe
the translation
annotations
to
where
boldface
stmt, stmt1
and stmt2ofstand
for the re-
Java a DynAlloy: Código
TACO: Análisis Eficiente de
Código Java
TACO: Translation of Annotated COde.
Utiliza una técnica eficiente para reducir las cotas
superiores de KodKod.
Consigue mejoras en tiempos de análisis de gran
magnitud.
Algunos experimentos muestran que consigue
equipararse o superar a otras herramientas
poderosas basadas en SMT solving y otras
técnicas
Ejemplo de un Problema
Generar instancias de AVLs
12
6
3
14
8
1. Árbol binario,
2. Ordenado,
3. Balanceado: |h(left(n)) - h(right(n))| <= 1
1
15
Técnica: Refinamiento
Automático de Cotas
Para encontrar una instancia el SAT solver
intenta encontrar (usando estrategas de poda
del espacio de estados) un árbol thiz, y
funciones para los campos root, h, left y right
tales que satisfacen el invariante de la
estructura.
Para AVLs
En lo que respecta al campo h, notemos que todas las
hojas tienen h = 0. Además, dado que estos son
árboles balanceados de a lo sumo 7 nodos, ningún
nodo satisface h(n) mayor a 3.
h=3
h=0
h=1
h=2
h=2
h=0
h=1
h=1
h=0
h=1
h=0
h=0
h=0
h=0
Para AVLs
Como los nodos son objetos, un nodo puede estar
almacenado en diferentes direcciones (en momentos
diferentes). Por ejemplo:
N0
N1
N2
2
5
3
N3
6
4
N3
N4
N0
N2
2
5
3
6
4
N4
N1
Para AVLs
Pero forzaremos que los nodos sean recorridos en
Breadth First Search
N0
N1
N3
2
3
5
6 N2
4 N4
N0
Para AVLs
N1
N3
2
5
3
6
4
N4
Es posible que N0 apunte a un nodo que no sea ni
N1 ni N2?
Es posible que N2 sea apuntado por algo que no
sea N0?
N0
N1
N2
2
3
5
No es un AVL!
N2
Casos Insatisfactibles
Por ejemplo, para un árbol con a lo sumo 7 nodos,
h(n)<=3 for all node n.
Left(N0) es o bien N1 o null (pero no N2, N3,...)
Right(N0) es N1, N2 o null (pero no N3, N4,...)
Right(Ni) != N2 para i != 0.
Casos Insatisfactibles
En clases con invariantes complejos, estos valores
corresponden a tuplas en campos, y por lo tanto
a variables proposicionales en la traducción
KodKod.
Si podemos eliminar estos casos insatisfactibles,
el SAT-solver tendría que intentar asignaciones de
un menor número de variables.
Esta observación es general, no sólo para AVLs!!!
Refinar cotas se reduce a...
Forzar que se asignen direcciones a los nodos de
acuerdo a un recorrido BFS.
Descubrir las variables que corresponden a casos
insatisfactibles.
Hacer esto de manera automática.
La Técnica:
Instrumentar el modelo relacional con fórmulas que
fuercen la asignación de direcciones a nodos en BFS.
Chequear, para el modelo resultante, la satisfactibilidad
de cada par correspondiente a cada campo de cada
clase.
Instrumenting the model
Regla 2: Dos nodos con el mismo padre se etiquetan de
Regla
1: La nuevamente
raíz se etiqueta
con N0.
Aplicando
la
Regla
2
izquierda a derecha
N0
root
5
N1
3
2
N4
6
4
N3
N2
Chequeo de Satisfactibilidad
Enfoque Naive: Usar un cluster para
chequear la satisfact. de cada par en cada
campo
Problema
N0.left = N0,
Generar un AVL con 20 nodos
N0.left = N1,
no termina.
...
N0.h = 0,
No se tienen aún
N0.h = 1,
cotas más
...
ajustadas!
Para 20 nodos, se deben realizar
2120 chequeos.
Un Enfoque efectivo
SATs
p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0
UNSATs
Bound
p0
p3
p6
p9
p1
p4
p7
p10
p2
p5
p8
p11
p0
p9
p10
p1
p2
p6
p3
p11
p7
p4
p5
p8
TIMEOUTS
Sobre “Cotas Ajustadas”
Consideremos la siguiente estructura y su representación
Como vimos, los campos son matrices (relaciones), representadas por variables
booleanas (una por celda)
Sobre “Cotas Ajustadas”
La rotura de simetrías hace a algunas de éstas no satisfactibles!
Rotura de simetrías: “header es null o N0, y Ni.next es N.(i+1) o null”
Esto permite eliminar variables de celdas no satisfactibles:
Manejo Booleano de Aritmética
Los dominios numéricos se pueden capturar por su
representación en bajo nivel:
sig integer {
bit31: boolean,
...
bit0: boolean
}
pred intEQ[i1, i2 : integer] {
i1.bit31 = i2.bit31
i1.bit30 = i2.bit30
...
i1.bit00 = i2.bit00
}
SAT Solving Incremental
Básicamente: permite agregar más restricciones “on the fly”,
sin tener que reiniciar el proceso de SAT solving
Esto se usa para obtener cobertura óptima (acotada) con la
cantidad mínima de tests
Evaluación
Aquí tenemos algunas comparaciones del enfoque con otras
herramientas basadas en constraint solving
Algunos Casos no Capturados
por Otras Herramientas
No captado por Kiasan
No captado ni por Kiasan ni por PEX
Evaluación (cont.)
Segunda comparación: herramientas de generación de tests
sobre estructuras complejas alojadas en memoria dinámica
En Conclusión
La generación de tests es crucial para el testing
Es en general muy costosa, y se realiza de manera
manual
Es relativamente fácil de automatizar para rutinas con
parámetros de tipos básicos (e.g., generación aleatoria)
Si se busca conseguir buena cobertura, es en
general muy difícil
Si los tipos de datos manipulados son complejos, es
definitivamente muy difícil
Resumen de Técnicas de
Generación Automática
Generación Aleatoria
Generación Basada en Constraint Solving
Basada en SAT vs. basada en SMT vs. basada en búsqueda (incl.
model checking)
White box vs. black box
Generación exhaustiva acotada
Inherentemente “fuerza bruta”, aunque en general requiere
constraint solving
Descargar