test input generation for java containers using state matching willem visser corina pasareanu and...

40
Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA Ames Research Center

Upload: noah-wilkerson

Post on 04-Jan-2016

226 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Test Input Generation for Java Containers using

State Matching

Willem Visser Corina Pasareanu and Radek Pelanek

Automated Software Engineering GroupNASA Ames Research Center

Page 2: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Background• ISSTA 2004

– White-box Test Input Generation for Red-Black Trees• Symbolic Execution of structural invariants

– Korat-style

• Symbolic Execution of actual code

– Verdict• Got branch coverage for structures of < 7 nodes

– Could not go much higher either

• Satisfactory results, but is this how one would really test containers?

Page 3: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Background (2)• More natural to test using Black-box techniques

– Test cases based on API calls and parameters

• Additional inspiration from Paolo Tonella– Email exchange on comparing with his evolutionary

testing framework that works at the API level

• But there are many ways to do test generation at the API level…which way should we go– As many ways as we can!

• How to compare these?– Measure the coverage we get

Page 4: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

General Idea

SUT

ENV (m,n)

m is the seq. length of API calls &

n is the number of values used in the parameters of the calls

API…

put(v)del(v)

Evaluate different techniques for selecting

test-cases from ENV(m,n)to obtain maximum coverage

Page 5: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

SUT – Container Classes

• Binary Tree– 154 LOC– add(x), remove(x)

• Red-black Trees (java.util.TreeMap)– 580 LOC– put(x), remove(x)

• Fibonacci Heap– 286 LOC– Insert(x), delete(x), removeMin()

• Binomial Heap– 355 LOC– insert(x), delete(x), extractMin(), decreaseKey(x,y)

Page 6: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Coverage Measures

• Basic Block, i.e. Statement, Coverage– Simplest form of coverage– Aligned with “simple” bugs

• Predicate Coverage– Cover all combinations of a given set of predicates at

each branch in the code– Much harder coverage to obtain– Aligned with “deeper” behavioral bugs

• Question: why not seed bugs?– Only automatic way of doing this is through mutation

which is more likely to give easy bugs to find

Page 7: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Predicate Coverage

Cover all combinations of a given set of predicates at each branch in the code

Red-Black Tree Predicatesroot = null, e.left = null,

e.right = null, e.parent = null, e.color = BLACK

Page 8: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

public void add(int x) {Node current = root;

if (root == null) {gen(0, current, x, null, null);root = new Node(x);return;

}

while (current.value != x) {if (x < current.value) {

if (current.left == null) {gen(1, current, x, null, null);current.left = new Node(x);

} else {gen(2, current, x, null, null);current = current.left;

}} else {

if (current.right == null) {gen(3, current, x, null, null);current.right = new Node(x);

} else {gen(4, current, x, null, null);current = current.right;

}}

}}

Page 9: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

public static int gen_native(MJIEnv env, int objRef, int br, int n0, int x,int n1, int n2) {

String res = br + ",";

int temp;if (n0 == -1) {

res += "-";} else {

temp = env.getIntField(n0, null, "left");res += (temp == -1) ? "L-" : "L+";temp = env.getIntField(n0, null, "right");res += (temp == -1) ? "R-" : "R+";

}res += (n1 == -1) ? "P-" : "P+";if (n2 == -1) {

res += "B-";} else {

temp = env.getIntField(n2, null, "left");res += (temp == -1) ? "BL-" : "BL+";temp = env.getIntField(n2, null, "right");res += (temp == -1) ? "BR-" : "BR+";

}

if (!tests.contains(res)) {tests.add(res);System.out.println("Test case number " + tests.size() + " for '"

+ res + "': ");return tests.size();

}return 0;

}

Page 10: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Let’s Go Outside the Box

• Rather than over-approximate and refine, we under-approximate and refine– Clearly complements existing techniques

• If we restrict ourselves only to feasible behaviors when under-approximating then all safety property violations will be preserved

• Build on top of classic explicit-state model checking infrastructure

Page 11: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Classic Explicit-State SearchPROCEDURE dfs() { s = top(Stack); FOR all transitions t enabled in s DO s' = successor(s) after executing t; IF s' NOT IN VisitedStates THEN

Enter s' into VisitedStates; Push s' onto Stack; dfs(); END END; Pop s from Stack; }

INIT { Enter s0 into VisitedStates; Push s0 onto Stack; dfs(); }

Page 12: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Explicit-State (1-step) αSearchPROCEDURE dfs() { s = top(Stack); FOR all transitions t enabled in s DO s' = successor(s) after executing t; IF α(s‘) NOT IN VisitedStates THEN

Enter α(s‘) into VisitedStates; Push s' onto Stack; dfs(); END END; Pop s from Stack; }

INIT { Enter α(s0) into VisitedStates; Push s0 onto Stack; dfs(); }

Page 13: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

αSearch

1: x = 2;2: while (x>0) 3: x = x - 1;4: assert false;

Abstraction Mapping

p = (x>0)

Map concrete states to abstract states for state storing

1,p

2,p

3,p

Always traverse only feasible paths

Under-approximation of the behaviors

Page 14: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Symbolic Execution and αSearch

• Current implementation is for a simple input language – oCaml using Simplify as a decision procedure

• We would like to integrate the technique in Java Pathfinder (JPF) that supports symbolic execution (using the Omega Library)– To allow application to programs with complex data

structures (objects)• Idea

– Execute symbolically but along concrete path– Whenever the symbolic analysis can follow

alternatives, add predicates for the alternative path

Page 15: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

End of Part One

• Showed under-approximation based search with refinement– Backward weakest precondition based– Suggested forward symbolic execution based

• Part Two– Rather than automated refinement we use

user-provided abstractions– Motivation is to generate test-cases to

achieve high behavioral coverage for Java container classes

Page 16: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Explicit-State (1-step) αSearchPROCEDURE dfs() { s = top(Stack); FOR all transitions t enabled in s DO s' = successor(s) after executing t; IF α(s‘) NOT IN VisitedStates THEN

Enter α(s‘) into VisitedStates; Push s' onto Stack; dfs(); END END; Pop s from Stack; }

INIT { Enter α(s0) into VisitedStates; Push s0 onto Stack; dfs(); }

Page 17: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Techniques Considered• Random selection• Classic model checking

– State matching on complete state

• Abstraction search– State matching on abstract (partial) state

• Symbolic Execution– Complete matching using subsumption checks– Abstract matching

Page 18: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Framework

SUTwith

minor instrumentation

ENV

TestListener

Abstraction Mapping+

State StorageCoverage Manager

JPF

Page 19: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Sample Output

Test case number 77 for '15,L+R+P-REDroot': put(0);put(4);put(5);put(1);put(2);put(3);remove(4);

Unique ID for the testBranch Number Predicate Values

Test-case to achieve above coverage

Test case number 7 for '32,L-R-P+RED':X2(0) == X1(0) && X2(0) < X0(1) && X1(0) < X0(1)put(X0);put(X1);remove(X2);

Test case number 7 for '32,L-R-P+RED': put(1);put(0);remove(0);

Concrete

Symbolic

Path Conditionwith solutions

Symbolic TC

Page 20: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Environment SkeletonM : sequence lengthN : parameter valuesA : abstraction used

for (int i = 0; i < M; i++) { int x = Verify.random(N - 1); switch (Verify.random(1)) { case 0: put(x); break; case 1: remove(x); break;} }Verify.ignoreIf(checkAbstractState(A));

Page 21: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Symbolic Environment Skeleton

M : sequence lengthA : abstraction used

for (int i = 0; i < M; i++) {

SymbolicInteger x = new SymbolicInteger(“X“+i); switch (Verify.random(1)) { case 0: put(x); break; case 1: remove(x); break;} }Verify.ignoreIf(checkAbstractState(A));

Page 22: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Abstraction Search

• Map state to an abstract version and backtrack if the abstract state was seen before, i.e. discard test-case

• Mapping can be lossy or not• Abstraction mappings can be created by

the user/tester• Default abstraction mappings are provided

Page 23: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Default Mappings

• Structure of the heap of the program– e.g. structure of the containers

• Structure augmented with non-data fields• Structure augmented with symbolic

constraints on the data in the structure– This requires checking constraint

subsumption

Page 24: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Linearization Comparing Structures

1

2

3 4

5

1

2

3 4

5

1

2

3 4

5

1

2

3 4

5

1 2 3 -1 -1 4 -1 -1 5 -1 -1 1 2 3 -1 -1 4 -1 -1 5 -1 -1

1 2 3 -1 -1 4 -1 -1 5 -1 -1 1 2 3 -1 -1 4 -1 5 -1 -1 -1

Page 25: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

4 3

2

1

Linearization + Mapping

1

2

3 4

5

1b 2b 3r -1 -1 4r -1 -1 5b -1 -1

5

1b 2r 3r -1 -1 4r -1 -1 5r -1 -1

Linearization takes a mapping object as parameter to indicate how each node in the heap should be linearized.

In the example above each node gets, besides the unique identifier, a mapping of “r” if the original structure had a red node and “b” if the original structure had a black node in that position. If we also added the key values for each node the linearization might have looked something like: 1b6 2b4 3r3 -1 -1 4r5 -1 -1 5b7 -1 -1

Page 26: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Symbolic Execution

Symbolic Statex1

x2

x3 x4

x5 +x1 > x2 & x2 > x3 & x2 < x4 & x5 > x1

Shape Symbolic Constraints

Page 27: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Subsumption Checking

x1

x2

x3 x4

x5 +x1 > x2 & x2 > x3 & x2 < x4 & x5 > x1

x1

x2

x3 x4

x5 +x1 > x2 & x2 > x3 & x2 < x4 & x5 > x1

If only it was this simple!

Page 28: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Getting Ready for CheckingExistential Elimination

x1

x2

x3 x4

x5

PCs1 < s2 & s4 > s3 & s4 < s1 & s4 < s5 &s7 < s2 & s7 > s1

s1

s4 s2

s3 s5

+

s1,s2,s3,s4,s5 such that x1 = s1 & x2 = s4 & x3 = s3 & x4 = s5 & x5 = s2 & PC

x1 > x2 & x2 > x3 & x2 < x4 & x5 > x1

Page 29: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Bidirectional Subsumption Checking

• If new => old – backtrack

• If old => new – new is more general than old – replace old with new

• to increase chances of getting a match in the future – Continue on path from new, i.e. don’t backtrack

• Ultimately for each shape we want to use disjunction of constraints– Small technicality prevents us – bug in omega lib

Page 30: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Evaluation

• Red-Black Trees• Out of Memory runs are not reported• Breadth-first Search unless stated• Sequence Length = Values

for the non-symbolic searches• First compare under Branch Coverage

Page 31: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Exhaustive TechniquesBranch Coverage

Seq Cov Len Time MemFull MC 7 39 4.3 536 584

S+C+V 7 39 4.3 10.635 17.47

Sym – S+Sub 7 39 4.3 14.201 16.95

Optimal Branch Coverage is 39

Page 32: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Under-Approximation TechniquesBranch Coverage

Seq Cov Len Time MemS 21 39 6.1 57.353 72.07

S+C 18 39 5.8 32.577 21.16

Sym - S 7 39 4.3 10.054 15.43

Sym – S+C 7 39 4.3 11.998 10.76

Random 9 39 7 40.429 3.06

Optimal Branch Coverage is 39

Page 33: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Exhaustive TechniquesPredicate Coverage

Seq Cov Len Time MemFull MC 7 79 5.2 543 309

S+C+V 10 95 5.7 350 228

Sym – S+Sub 11 102 6.1 222 117

Optimal Predicate Coverage is 106

Page 34: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Under-Approximation TechniquesPredicate Coverage

Seq Cov Len Time MemS 25d 106 21.7 90 13.31

S+C 30 106 8.3 354 100

Sym - S 12 100 6.1 230 123.27

Sym – S+C 12 104 6.2 356 138

Random 60 106 30.1 61.459 7.74

Optimal Predicate Coverage is 106

Page 35: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Observations

• For a simple coverage such as branch coverage, all the techniques work well, including the exhaustive ones

• But making the coverage more “behavioral”, even by a small increment, kills off the exhaustive techniques

Page 36: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Observations

• Full Blown Model Checking doesn’t work here• Its close cousin, that only looks at the relevant

state at the relevant time, scales much better• Branch - full coverage after:

– MC: 536s & 584Mb– Complete: 10s & 17Mb

• Predicate – best coverage after:– MC: 79 covered with 543s & 309Mb– Complete: 95 covered with 350s & 228Mb

Page 37: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Observations

• Symbolic techniques have a slight edge over concrete ones for exhaustive analysis– Comparing for Predicate Coverage (10)

• Full Concrete(95): 350s & 228Mb• Full Symbolic(95): 123s & 62Mb

• Current results indicate symbolic under-approximation based search is less efficient than concrete

• Further experimentation required

Page 38: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Observations

• Random Search?– Seems to work rather well here

• It will always have an edge on memory, since it uses almost none

• It will most likely have an edge on speed, since it needs to do little additional work – it will however redo work often

• It will in general do worse on test-case length, since it requires longer sequences to achieve more complex coverage

Page 39: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Observations

• Search Order Matters for the lossy techniques– BFS is inherently better than DFS– On occasion though it is the other way round

Page 40: Test Input Generation for Java Containers using State Matching Willem Visser Corina Pasareanu and Radek Pelanek Automated Software Engineering Group NASA

Conclusions & Future Work

• Showed how predicate abstraction can be used for an under-approximation based search with refinement

• Showed how a lightweight variant, where the abstraction mapping is given and no refinement is done, can be used for bug-finding and test-case generation

• Goal: Derive predicates for analyzing containers automatically through the use of symbolic execution during refinement– Can we derive shape predicates automatically?