Upload
dusan
View
62
Download
0
Tags:
Embed Size (px)
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
Citation preview
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