Title: A Theory of Predicate-complete Test Coverage and Generation
1A Theory of Predicate-complete Test Coverage and
Generation
- Thomas Ball
- Testing, Verification and Measurement
- Microsoft Research
- May 2004
2Unit Test Generation
3Unit Test Generation
4Unit Test Generation
5Unit Test Generation
6MSIL Unit Test Tool a hybrid helper
- Goal
- capture developer knowledge ASAP
- via a strong set of unit tests
- to form a specification of the codes behavior
- How
- generate tests based on analysis of MSIL
- symbolic execution constraint satisfaction
- runtime analysis to check complicated invariants
- Facets
- complements specification-based test generation
- positive feedback cycle with programmer
7What criteria should guide unit test generation?
8Control-flow Coverage Criteria
- Statement/branch coverage widely used
- 100 coverage ? a bug-free program!!
- More stringent criteria
- modified-condition-decision, predicate,
data-flow, mutation, path,
9Predicate-complete Testing
- Predicates
- relational expression such as (xlt0)
- the expression (xlt0) (ygt0) has two predicates
- predicates come from program and safe runtime
semantics - Consider a program with m statements and n
predicates - predicates partition input domain
- m x 2n possible observable states S
- Goal of Predicate-complete Testing
- cover all reachable observable states R ? S
10PCT Coverage
- L2 if (A B) S else T
- L3 if (C D) U else V
- PCT requires covering all logical combinations
over A,B,C,D at - L2 and L3
- S, T, U and V
- Some combinations may not be reachable
11PCT Coverage does not imply Path Coverage
L1 if (xlt0) L2 skip else L3 x
-2 L4 x x 1 L5 if (xlt0) L6 A
12PCT Coverage does not imply Path Coverage
L1 if (xlt0) L2 skip else L3 x
-2 L4 x x 1 L5 if (xlt0) L6 A
13PCT Coverage does not imply Path Coverage
L1 if (xlt0) L2 skip else L3 x
-2 L4 x x 1 L5 if (xlt0) L6 A
14PCT Coverage does not imply Path Coverage
L1 if (xlt0) L2 skip else L3 x
-2 L4 x x 1 L5 if (xlt0) L6 A
15Path Coverage does not imply PCT Coverage
L1 if (p) L2 if (q) L3 x0 L4
ypq
16Path Coverage does not imply PCT Coverage
L1 if (p) L2 if (q) L3 x0 L4
ypq
17Denominator Problem
- Coverage metrics require a denominator
- e.g. statements executed / total statements
- Easy to define for observable states
- executed observable states / (m x 2n)
- But (m x 2n) is not a very good denominator!
- most observable states will not be reachable
- R ltltlt S
18Upper and Lower Bounds
- Bound reachable observable states
- modal transition systems and predicate
abstraction - L / U defines goodness of abstraction
- Test generation using lower bound L
- Refinement to increase L / U ratio
19Overview
- Upper and lower bounds
- Example
- Test case generation
- Refinement
- Discussion
- Conclusions
20Abstraction Construction
21Predicate Abstraction
- if Q ? SP(P,s)
- then (P,Q) ? onto
22Example
23Upper Bound May-Reachability
24Upper Bound May-Reachability
25Pessimistic Lower Bound
a
onto
b
may
c
total
d
26Pessimistic Lower Bound
a
onto
b
may
c
total
d
27Pessimistic Lower Bound
a
onto
b
may
c
total
d
28Postdominance
- pd(a) a ? ? pd(b) (a,b) ? may
29Postdominance
- pd(a) a ? ? pd(b) (a,b) ? may
30Postdominance
- pd(a) a ? ? pd(b) (a,b) ? may
31Postdominance
- pd(a) a ? ? pd(b) (a,b) ? may
32Postdominance
- pd(a) a ? ? pd(b) (a,b) ? may
33Optimistic Lower Bound
34Overview
- Upper and lower bounds
- Example
- Test case generation
- Refinement
- Discussion
- Conclusions
35Example
void partition(int a) assume(a.length()gt2)
int pivot a0 int lo 1 int hi
a.length()-1 while (lolthi) while
(aloltpivot) lo while
(ahigtpivot) hi-- if (lolthi)
swap(a,lo,hi)
void partition(int a) assume(a.length()gt2)
int pivot a0 int lo 1 int hi
a.length()-1 while (lolthi) while
(aloltpivot) lo while
(ahigtpivot) hi-- if (lolthi)
swap(a,lo,hi)
36Observation Vector
- lolthi, lolthi, aloltpivot, ahigtpivot
- lolthi ? lolthi
- ?lolthi ? lolthi ? (aloltpivot ? ?ahigtpivot)
- ? (?aloltpivot ?
ahigtpivot) - Only 10/16 observations possible
37void partition(int a) assume(a.length()gt2)
int pivot a0 int lo 1 int hi
a.length()-1 L0 while (lolthi) L1
L2 while (aloltpivot) L3 lo
L4 L5 while (ahigtpivot) L6
hi-- L7 L8 if (lolthi) L9
swap(a,lo,hi) LA LB LC
13 labels x 10 observations 130 observable
states
But, program constrains reachable observable
states greatly.
38Boolean Program
void partition() decl lt, le, al, ah
enforce ( (ltgtle)
((!ltle)gt(al!ah)(!alah)) )
lt,le,al,ah T,T,, L0 while (le) L1
L2 while (al) L3 lt,le,al
(!lt ? F), lt, L4 L5 while (ah)
L6 lt,le,ah (!lt ? F), lt, L7
L8 if (lt) L9 al,ah
!ah,!al LA LB LC
39State Space of Boolean Program
lolthi, lolthi, aloltpivot, ahigtpivot
Upper Bound 49 states
40(No Transcript)
41Overview
- Upper and lower bounds
- Example
- Test case generation
- Refinement
- Discussion
- Conclusions
42Test Generation
- DFS of Lp generates covering set of paths
- Symbolically execute paths to generate tests
- Run program on tests to find errors and compute
coverage of observable states
43(No Transcript)
44(No Transcript)
45Generated Inputs
void partition(int a) assume(a.length()gt2)
int pivot a0 int lo 1 int hi
a.length()-1 L0 while (lolthi) L1
L2 while (aloltpivot) L3 lo
L4 L5 while (ahigtpivot) L6
hi-- L7 L8 if (lolthi) L9
swap(a,lo,hi) LA LB LC
- (L0TTTT,L4FTFT) 0,-8,1
- (L0TTTT,L4TTFT) 0,-8,2,1
- (L0TTTT,L4TTTT) 0,-8,-8,1
- (L0TTTF,L4TTFF) 1,-7,3,0
- (L0TTTF,L4FTTF) 0,-7,-8
- (L0TTTF,L4TTTF) 1,-7,-7,0
- (L0TTFT,L7TTFF) 0,2,-8,1
- (L0TTFT,L7FTFT) 0,1,2
- (L0TTFT,L7TTFT) 0,3,1,2
- (L0TTFF,L0TTTT) 1,2,-1,0
46Results
- Buggy partition function
- U49, L43, Tested42
- Fixed partition function
- U56, L37, Tested43
- What about the remaining 13 states?
47Overview
- Upper and lower bounds
- Example
- Test case generation
- Refinement
- Discussion
- Conclusions
48Unreachable State
L7FFFT (logthi) (alogtpivot)
(ahigtpivot) But code maintains invariant
that ?0ltiltlo, ailtpivot
void partition(int a) assume(a.length()gt2)
int pivot a0 int lo 1 int hi
a.length()-1 L0 while (lolthi) L1
L2 while (aloltpivot) L3 lo
L4 L5 while (ahigtpivot) L6
hi-- L7 L8 if (lolthi) L9
swap(a,lo,hi) LA LB LC
49Refinement
50New Observation Vector
- lolthi, lolthi, lohi1,
- aloltpivot, ahigtpivot,
- alo-1ltpivot, ahi1gtpivot
-
- Only 48/128 observations possible
- For this set of predicates, Lp U
51Overview
- Upper and lower bounds
- Example
- Test case generation
- Refinement
- Discussion
- Conclusions
52Discussion
- Comparison to bisimulation
- Completeness of abstractions
- Related work
53Bisimulation
54Bisimulation
55Abstraction Completeness
56Abstraction Completeness
57Related Work
- Test coverage criteria
- Symbolic execution/constraint satisfaction
- Abstraction-guided test generation
- Three-valued model checking
- Modal transition systems
58Conclusions
- PCT coverage
- new form of state-based coverage
- similar to path coverage but finite
- Upper and lower bounds
- computed using predicate abstraction and modal
transitions - use lower bound to guide test generation
- refine bounds
59Directions
- How does PCT work in practice?
- MUTT implementation underway
- Other problems
- the oracle problem
- specification inference
- compositional test generation
- object construction
60For More Information
- http//research.microsoft.com/tvm/
- A theory of predicate-complete test coverage and
generation - MSR-TR-2004-28, April 2004
- to appear Third International Symposium on Formal
Methods for Components and Objects (FMCO 2004),
November 2004