OMEN: A Strategy for Testing Object-Oriented Software

Post on 23-Feb-2016

60 views 0 download

Tags:

description

OMEN: A Strategy for Testing Object-Oriented Software . Amie L. Souter & Lori L. Pollock ISSTA 2000. Dept. of Computer and Information Sciences. Object-Oriented Programming. Features Classes, Objects, and Inheritance Polymorphism and Dynamic Binding Programming Style - PowerPoint PPT Presentation

transcript

OMEN: A Strategy for Testing Object-Oriented Software

Amie L. Souter&

Lori L. PollockISSTA 2000

Dept. of Computer and Information Sciences

Object-Oriented Programming

• Features– Classes, Objects, and Inheritance – Polymorphism and Dynamic Binding

• Programming Style– Modularity: many small methods– Objects– Code reuse through inheritance– Complex class interactions– Heavy use of libraries

Class Stack{ int myStack[]; int top;

1 public Stack(int s){ myStack = new int[s]; 2 top = 0; }3 public void push(int obj){ myStack[top++] = obj; }4 public int pop(){ 5 if(size() == 0) return error; 6 int temp = myStack[top-1];7 top--;8 return temp; } 9 public int size() { return top; }10 public int top() { return myStack[top-1]; }11 public boolean isEmpty() { return top == 0; }12 public void example() { push(10); if(size() == 5) do_something++; }

Illustrating Kinds of DEF-USE PairsIllustrating Kinds of DEF-USE Pairs

intra-methodintra-method

traditional du analysis Weyuker:85

Class Stack{ int myStack[]; int top;

1 public Stack(int s){ myStack = new int[s]; 2 top = 0; }3 public void push(int obj){ myStack[top++] = obj; }4 public int pop(){ 5 if(size() == 0) return error; 6 int temp = myStack[top-1];7 top--;8 return temp; } 9 public int size() { return top; }10 public int top() { return myStack[top-1]; }11 public boolean isEmpty() { return top == 0; }12 public void example() { push(10); if(size() == 5) do_something++; }

Illustrating Kinds of DEF-USE PairsIllustrating Kinds of DEF-USE Pairs

intra-methodintra-method

traditional du analysis Weyuker:85

Class Stack{ int myStack[]; int top;

1 public Stack(int s){ myStack = new int[s]; 2 top = 0; }3 public void push(int obj){ myStack[top++] = obj; }4 public int pop(){ 5 if(size() == 0) return error; 6 int temp = myStack[top-1];7 top--;8 return temp; } 9 public int size() { return top; }10 public int top() { return myStack[top-1]; }11 public boolean isEmpty() { return top == 0; }12 public void example() { push(10); if(size() == 5) do_something++; }

Illustrating Kinds of DEF-USE PairsIllustrating Kinds of DEF-USE Pairs

inter-methodinter-method

interprocedural du analysis Harrold:89

Class Stack{ int myStack[]; int top;

1 public Stack(int s){ myStack = new int[s]; 2 top = 0; }3 public void push(int obj){ myStack[top++] = obj; }4 public int pop(){ 5 if(size() == 0) return error; 6 int temp = myStack[top-1];7 top--;8 return temp; } 9 public int size() { return top; }10 public int top() { return myStack[top-1]; }11 public boolean isEmpty() { return top == 0; }12 public void example() { push(10); if(size() == 5) do_something++; }

Illustrating Kinds of DEF-USE PairsIllustrating Kinds of DEF-USE Pairs

inter-methodinter-method

interprocedural du analysis Harrold:89

Class Stack{ int myStack[]; int top;

1 public Stack(int s){ myStack = new int[s]; 2 top = 0; }3 public void push(int obj){ myStack[top++] = obj; }4 public int pop(){ 5 if(size() == 0) return error; 6 int temp = myStack[top-1];7 top--;8 return temp; } 9 public int size() { return top; }10 public int top() { return myStack[top-1]; }11 public boolean isEmpty() { return top == 0; }12 public void example() { push(10); if(size() == 5) do_something++; }

Illustrating Kinds of DEF-USE PairsIllustrating Kinds of DEF-USE Pairs

inter-methodinter-method

interprocedural du analysis Harrold:89

Class Stack{ int myStack[]; int top;

1 public Stack(int s){ myStack = new int[s]; 2 top = 0; }3 public void push(int obj){ myStack[top++] = obj; }4 public int pop(){ 5 if(size() == 0) return error; 6 int temp = myStack[top-1];7 top--;8 return temp; } 9 public int size() { return top; }10 public int top() { return myStack[top-1]; }11 public boolean isEmpty() { return top == 0; }12 public void example() { push(10); if(size() == 5) do_something++; }

Illustrating Kinds of DEF-USE PairsIllustrating Kinds of DEF-USE Pairs

intra-classintra-class

Intra-class du analysis Harrold & Rothermel: 94

Class Stack{ int myStack[]; int top;

1 public Stack(int s){ myStack = new int[s]; 2 top = 0; }3 public void push(int obj){ myStack[top++] = obj; }4 public int pop(){ 5 if(size() == 0) return error; 6 int temp = myStack[top-1];7 top--;8 return temp; } 9 public int size() { return top; }10 public int top() { return myStack[top-1]; }11 public boolean isEmpty() { return top == 0; }12 public void example() { push(10); if(size() == 5) do_something++; }

Illustrating Kinds of DEF-USE PairsIllustrating Kinds of DEF-USE Pairs

intra-classintra-class

Intra-class du analysis Harrold & Rothermel: 94

Class Stack{ int myStack[]; int top;

1 public Stack(int s){ myStack = new int[s]; 2 top = 0; }3 public void push(int obj){ myStack[top++] = obj; }4 public int pop(){ 5 if(size() == 0) return error; 6 int temp = myStack[top-1];7 top--;8 return temp; } 9 public int size() { return top; }10 public int top() { return myStack[top-1]; }11 public boolean isEmpty() { return top == 0; }12 public void example() { push(10); if(size() == 5) do_something++; }

Illustrating Kinds of DEF-USE PairsIllustrating Kinds of DEF-USE Pairs

intra-classintra-class

Intra-class du analysis Harrold & Rothermel: 94

Class genericStack{ Array myStack;

1 public genericStack() { myStack = new Array(); }2 public Object top() { return myStack.back(); }3 public void push(Obj o){ myStack.pushBack(o); }4 public Object pop() { return myStack.popBack(); } 5 public bool isEmpty() { return myStack.isEmpty(); }6 public int size() { return myStack.size(); }}

DEF-USE Pairs Involving Inter-Class InteractionsDEF-USE Pairs Involving Inter-Class Interactions

Class Array { Object myStorage[]; int myLength;

1 public Array() { myStorage = new Object[SIZE];2 myLength = 0; }3 public Object back() { return myStorage[myLength-1];}4 public Object popBack() { return myStorage[--myLength];}5 public void pushBack(Obj o){ add(o); } 6 public Object front(Obj o) { return myStorage[0]; }7 public bool isEmpty() { return (myLength == 0) }8 public int size() { return myLength; }9 public void add(Obj o){ myStorage[myLength++] = o; }

//Array has 46 other methods}

Inter-class du analysis Souter & Pollock:99

Class genericStack{ Array myStack;

1 public genericStack() { myStack = new Array(); }2 public Object top() { return myStack.back(); }3 public void push(Obj o){ myStack.pushBack(o); }4 public Object pop() { return myStack.popBack(); } 5 public bool isEmpty() { return myStack.isEmpty(); }6 public int size() { return myStack.size(); }}

DEF-USE Pairs Involving Inter-Class InteractionsDEF-USE Pairs Involving Inter-Class Interactions

Class Array { Object myStorage[]; int myLength;

1 public Array() { myStorage = new Object[SIZE];2 myLength = 0; }3 public Object back() { return myStorage[myLength-1];}4 public Object popBack() { return myStorage[--myLength];}5 public void pushBack(Obj o){ add(o); } 6 public Object front(Obj o) { return myStorage[0]; }7 public bool isEmpty() { return (myLength == 0) }8 public int size() { return myLength; }9 public void add(Obj o){ myStorage[myLength++] = o; }

//Array has 46 other methods}

Inter-class du analysis Souter & Pollock:99

Class genericStack{ Array myStack;

1 public genericStack() { myStack = new Array(); }2 public Object top() { return myStack.back(); }3 public void push(Obj o){ myStack.pushBack(o); }4 public Object pop() { return myStack.popBack(); } 5 public bool isEmpty() { return myStack.isEmpty(); }6 public int size() { return myStack.size(); }}

DEF-USE Pairs Involving Inter-Class InteractionsDEF-USE Pairs Involving Inter-Class Interactions

Class Array { Object myStorage[]; int myLength;

1 public Array() { myStorage = new Object[SIZE];2 myLength = 0; }3 public Object back() { return myStorage[myLength-1];}4 public Object popBack() { return myStorage[--myLength];}5 public void pushBack(Obj o){ add(o); } 6 public Object front(Obj o) { return myStorage[0]; }7 public bool isEmpty() { return (myLength == 0) }8 public int size() { return myLength; }9 public void add(Obj o){ myStorage[myLength++] = o; }

//Array has 46 other methods}

Inter-class du analysis Souter & Pollock:99

Class genericStack{ Array myStack;

1 public genericStack() { myStack = new Array(); }2 public Object top() { return myStack.back(); }3 public void push(Obj o){ myStack.pushBack(o); }4 public Object pop() { return myStack.popBack(); } 5 public bool isEmpty() { return myStack.isEmpty(); }6 public int size() { return myStack.size(); }}

DEF-USE Pairs Involving Inter-Class InteractionsDEF-USE Pairs Involving Inter-Class Interactions

Class Array { Object myStorage[]; int myLength;

1 public Array() { myStorage = new Object[SIZE];2 myLength = 0; }3 public Object back() { return myStorage[myLength-1];}4 public Object popBack() { return myStorage[--myLength];}5 public void pushBack(Obj o){ add(o); } 6 public Object front(Obj o) { return myStorage[0]; }7 public bool isEmpty() { return (myLength == 0) }8 public int size() { return myLength; }9 public void add(Obj o){ myStorage[myLength++] = o; }

//Array has 46 other methods}

Inter-class du analysis Souter & Pollock:99

Class genericStack{ Array myStack;

1 public genericStack() { myStack = new Array(); }2 public Object top() { return myStack.back(); }3 public void push(Obj o){ myStack.pushBack(o); }4 public Object pop() { return myStack.popBack(); } 5 public bool isEmpty() { return myStack.isEmpty(); }6 public int size() { return myStack.size(); }}

DEF-USE Pairs Involving Inter-Class InteractionsDEF-USE Pairs Involving Inter-Class Interactions

Class Array { Object myStorage[]; int myLength;

1 public Array() { myStorage = new Object[SIZE];2 myLength = 0; }3 public Object back() { return myStorage[myLength-1];}4 public Object popBack() { return myStorage[--myLength];}5 public void pushBack(Obj o){ add(o); } 6 public Object front(Obj o) { return myStorage[0]; }7 public bool isEmpty() { return (myLength == 0) }8 public int size() { return myLength; }9 public void add(Obj o){ myStorage[myLength++] = o; }

//Array has 46 other methods}

Inter-class du analysis Souter & Pollock:99

Research GoalsTo develop a new approach to testing object-oriented software that:• Provides structural testing tailored to OO codes

– association between objects and fields– include object creation site with def-use pair– handle complex class interactions

• Program representation scales to large software systems• Provides feedback to the tester

– Provides information on external influences of the testing results– Provides the tester with direction in how to test an incomplete

program

Outline• Object-Oriented Program Characteristics• Illustration of Def-Use Pairs• Research Goals• Our Solution

– Basic Object Manipulations– Annotated Points-to Escape Graph– OMEN: Test Tuple Construction Algorithm

• Work in Progress

Basic Object Manipulationscopy r1 = r2 read of reference r2

write of reference r1load r1 = r2.f read of reference r2

read of field r2.fwrite to r1

store r1.f = r2 read of reference r2read of reference r1write to field r1.f

global load r = cl.f read of class variable fwrite to reference r

global store cl.f = r read of reference rwrite to class variable cl.f

return r read of reference robject creationr=new Object( … )

create a new objectwrite to reference rMOD and USE side eff ects

method invocationsr = r0.methodname( … )

write to reference rMOD and USE side eff ects

Basic Object Manipulationscopy r1 = r2 read of reference r2

write of ref erence r1load r1 = r2.f read of reference r2

read of field r2.fwrite to r1

store r1.f = r2 read of reference r2read of reference r1write to field r1.f

global load r = cl.f read of class variable fwrite to ref erence r

global store cl.f = r read of reference rwrite to class variable cl.f

return r read of reference robject creationr=new Object( … )

create a new objectwrite to ref erence rMOD and USE side eff ects

method invocationsr = r0.methodname( … )

write to ref erence rMOD and USE side eff ects

Basic Object Manipulationscopy r1 = r2 read of reference r2

write of reference r1load r1 = r2.f read of reference r2

read of field r2.fwrite to r1

store r1.f = r2 read of reference r2read of reference r1write to field r1.f

global load r = cl.f read of class variable fwrite to reference r

global store cl.f = r read of reference rwrite to class variable cl.f

return r read of reference robject creationr=new Object( … )

create a new objectwrite to reference rMOD and USE side eff ects

method invocationsr = r0.methodname( … )

write to reference rMOD and USE side eff ects

Points-to-Escape-Graph

Terminology• Nodes

– inside– outside– load– return value

• Edges– inside– outside

e

this

temp

next

data

Node insert(Object e) { Node temp = new Node (e,this); return temp; }

Whaley & Rinard: OOPSLA99

Extensions to the Points-to-Escape Graph:APE Graph

1: public push( Object e){

2: if(top == null)

3: top = new Node(e, null);

4: else

5: top = top.insert(e);

}

6: Node (Object e, Node n ){

7: data = e;

8: next = n;

}

this

e

Extensions to the Points-to-Escape Graph:APE Graph

1: public push( Object e){

2: if(top == null)

3: top = new Node(e, null);

4: else

5: top = top.insert(e);

}

6: Node (Object e, Node n ){

7: data = e;

8: next = n;

}

this

e

top,2,load

Extensions to the Points-to-Escape Graph:APE Graph

1: public push( Object e){

2: if(top == null)

3: top = new Node(e, null);

4: else

5: top = top.insert(e);

}

6: Node (Object e, Node n ){

7: data = e;

8: next = n;

}

top,3,store

data,3-7,store

next,3-8,store

T

this

e

top,2,load

3

OMEN - Test Tuple Construction Algorithm

Computes a set of testing tuples for the component under test, based on object manipulations.Input: set of call graphs for component under testOutput: set of testing tuples for component under test• Traverse call graph in topological order

– Process each method’s APE graph• For each store annotation per unmarked APE graph edge

– find the associated loads occurring after the store– find object creation site associated with the tuple

• depends on the type of source node of the APE graph– report feedback

• using the escape information of the APE graph

Traverse the Call Graphin Topological Order

main

Stack

push

isempty

pop

println

Node insert get remove

Traverse the Call Graphin Topological Order

main: 1

Stack:2

push: 3

isempty:6

pop:7

println:10

Node:4 insert:5 get:8 remove:9

Processing a Method’s APE Graph

20Integer 20

x,22

s,18 18

20-6-29

20-4

top:1

top:2

top:3

next:4

next:5

next:6

next:7data:8data:9

Edge # StackClient Tuples

top:1 top(<18-1>,<20-3>, 18)

top:1 top(<18-1>,<22-9-16>, 18)

top:1 top(<18-1>,<21-16>, 18)

top:1,2,3 top(<22-13>,<22-9-16>, 18)

Edge # Annotations

top:1 top 21-16, loadtop 22(21)-9-16, loadtop 20(19)-3,loadtop 18-1, storetop 22(21)-13, store

Processing a Method’s APE Graph

20Integer 20

x,22

s,18 18

20-6-29

20-4

top:1

top:2

top:3

next:4

next:5

next:6

next:7data:8data:9

Edge # StackClient Tuples

top:1 top(<18-1>,<20-3>, 18)

top:1 top(<18-1>,<22-9-16>, 18)

top:1 top(<18-1>,<21-16>, 18)

top:1,2,3 top(<22-13>,<22-9-16>, 18)

Edge # Annotations

top:1 top 21-16, loadtop 22(21)-9-16, loadtop 20(19)-3,loadtop 18-1, storetop 22(21)-13, store

Processing a Method’s APE Graph

20Integer 20

x,22

s,18 18

20-6-29

20-4

top:1

top:2

top:3

next:4

next:5

next:6

next:7data:8data:9

Edge # StackClient Tuplesfi eld(<def>,<use>, <cs>)

top:1 top(<18-1>,<20-3>, 18)

top:1 top(<18-1>,<22-9-16>, 18)

top:1 top(<18-1>,<21-16>, 18)

top:1,2,3 top(<22-13>,<22-9-16>, 18)

Edge # Annotations

top:1 top 21-16, loadtop 22(21)-9-16, loadtop 20(19)-3,loadtop 18-1, storetop 22(21)-13, store

Avoiding Duplicate TuplesThrough Marking

top,3,store

data,3-7,store

next,3-8,storeT

this

e

1

1

top,2,load 2

3 4

data, 4-10-7, store

next,4

-10-8,

store

top,4,storeMarked edge

Non-marked edge

Edges are marked during interprocedural merges of ape graph construction.

Processing Incomplete Components

18

x,22

s,18top:1

top:2top:3top:4

Edge # StackClient Tuples

top:1 top(<18-1>,<20-3>, 18)

top:1,2,3 top(<22-13>,<22-9-16>, 18)top:4 top(<22-13>, <21-16>, 18)

Feedback: value loaded is potentially changed by method outside CUT.

Edge # Annotations

top:4 top 22(21)-13, storetop 21-16, load

Processing Incomplete Components

x,22

s,18top:1

top:2top:3top:4

Edge # StackClient Tuples

top:1 top(<18-1>,<20-3>, 18)

top:1,2,3 top(<22-13>,<22-9-16>, 18)top:4 top(<22-13>, <21-16>, 18)

Feedback: value loaded is potentially changed by method outside CUT.

Edge # Annotations

top:4 top 22(21)-13, storetop 21-16, load

Processing Incomplete Components

x,22

s,18top:1

top:2top:3top:4

Edge # StackClient Tuplesfi eld(<def>, <use>,<cs>)

top:1 top(<18-1>,<20-3>, 18)

top:1,2,3 top(<22-13>,<22-9-16>, 18)top:4 top(<22-13>, <21-16>, 18)

Feedback: value loaded is potentially changed by method outside CUT.

Edge # Annotations

top:4 top 22(21)-13, storetop 21-16, load

Work in ProgressAPE Graph• Implementation of the APE graph• Empirical study of the space and time requirements• Empirical characterization study of the object manipulations in real object-oriented codes

Test Tuple Construction Algorithm• Algorithm extensions to include coverage for object manipulations based on references only• Algorithm modifications - more sophisticated techniques to eliminate infeasible paths• Evaluation of the algorithm