Systematic Software Testing Using Test Abstractions Darko Marinov RIO Summer School Rio Cuarto, Argentina February 2011.

Slides:



Advertisements
Similar presentations
Korat Automated Testing Based on Java Predicates Chandrasekhar Boyapati, Sarfraz Khurshid, Darko Marinov MIT ISSTA 2002 Rome, Italy.
Advertisements

A System to Generate Test Data and Symbolically Execute Programs Lori A. Clarke September 1976.
Introducing Formal Methods, Module 1, Version 1.1, Oct., Formal Specification and Analytical Verification L 5.
Abstraction and Modular Reasoning for the Verification of Software Corina Pasareanu NASA Ames Research Center.
1 Symbolic Execution for Model Checking and Testing Corina Păsăreanu (Kestrel) Joint work with Sarfraz Khurshid (MIT) and Willem Visser (RIACS)
1/20 Generalized Symbolic Execution for Model Checking and Testing Charngki PSWLAB Generalized Symbolic Execution for Model Checking and Testing.
SOFTWARE TESTING. INTRODUCTION  Software Testing is the process of executing a program or system with the intent of finding errors.  It involves any.
Symbolic execution © Marcelo d’Amorim 2010.
1 of 24 Automatic Extraction of Object-Oriented Observer Abstractions from Unit-Test Executions Dept. of Computer Science & Engineering University of Washington,
Automated creation of verification models for C-programs Yury Yusupov Saint-Petersburg State Polytechnic University The Second Spring Young Researchers.
Towards a Lightweight Model of BGP Safety Matvey Arye Princeton University Joint work with: Rob Harrison, Richard Wang, Jennifer Rexford (Princeton) Pamela.
1 Today Another approach to “coverage” Cover “everything” – within a well-defined, feasible limit Bounded Exhaustive Testing.
Reference Book: Modern Compiler Design by Grune, Bal, Jacobs and Langendoen Wiley 2000.
Efficient Software Model Checking of Data Structure Properties Paul T. Darga Chandrasekhar Boyapati The University of Michigan.
Efficient Modular Glass Box Software Model Checking Michael Roberson Chandrasekhar Boyapati The University of Michigan.
Generative Programming. Generic vs Generative Generic Programming focuses on representing families of domain concepts Generic Programming focuses on representing.
272: Software Engineering Fall 2012 Instructor: Tevfik Bultan Lecture 8: Semi-automated test generation via UDITA.
Korat: Automated Testing Based on Java Predicates Chandrasekhar Boyapati 1, Sarfraz Khurshid 2, and Darko Marinov 3 1 University of Michigan Ann Arbor.
Formal Techniques for Verification Using SystemC By Nasir Mahmood.
CS527: (Advanced) Topics in Software Engineering Overview of Software Quality Assurance Tao Xie ©D. Marinov, T. Xie.
Programming Languages and Paradigms Object-Oriented Programming.
Chandrasekhar Boyapati (Google) Sarfraz Khurshid (University of Texas)
Reverse Engineering State Machines by Interactive Grammar Inference Neil Walkinshaw, Kirill Bogdanov, Mike Holcombe, Sarah Salahuddin.
CS527 Topics in Software Engineering (Software Testing and Analysis) Darko Marinov September 15, 2011.
Object-Oriented Software Testing. C-S 5462 Object-Oriented Software Testing Research confirms that testing methods proposed for procedural approach are.
CUTE: A Concolic Unit Testing Engine for C Technical Report Koushik SenDarko MarinovGul Agha University of Illinois Urbana-Champaign.
C++ Code Analysis: an Open Architecture for the Verification of Coding Rules Paolo Tonella ITC-irst, Centro per la Ricerca Scientifica e Tecnologica
Class Specification Implementation Graph By: Njume Njinimbam Chi-Chang Sun.
Korat: Automated Testing Based on Java Predicates
Chapter 1 Introduction Dr. Frank Lee. 1.1 Why Study Compiler? To write more efficient code in a high-level language To provide solid foundation in parsing.
Introduction Algorithms and Conventions The design and analysis of algorithms is the core subject matter of Computer Science. Given a problem, we want.
272: Software Engineering Fall 2012 Instructor: Tevfik Bultan Lecture 6: Exhaustive Bounded Testing and Feedback-Directed Random Testing.
Generative Programming. Automated Assembly Lines.
Introduction to Software Testing. Types of Software Testing Unit Testing Strategies – Equivalence Class Testing – Boundary Value Testing – Output Testing.
Code Contracts Parameterized Unit Tests Tao Xie. Example Unit Test Case = ? Outputs Expected Outputs Program + Test inputs Test Oracles 2 void addTest()
CS527 Topics in Software Engineering (Software Testing and Analysis) Darko Marinov September 9, 2010.
Today’s Agenda  Reminder: HW #1 Due next class  Quick Review  Input Space Partitioning Software Testing and Maintenance 1.
1 Test Selection for Result Inspection via Mining Predicate Rules Wujie Zheng
Symbolic Execution with Abstract Subsumption Checking Saswat Anand College of Computing, Georgia Institute of Technology Corina Păsăreanu QSS, NASA Ames.
Automated Patch Generation Adapted from Tevfik Bultan’s Lecture.
Xusheng Xiao North Carolina State University CSC 720 Project Presentation 1.
jFuzz – Java based Whitebox Fuzzing
Directed Random Testing Evaluation. FDRT evaluation: high-level – Evaluate coverage and error-detection ability large, real, and stable libraries tot.
A Test Case + Mock Class Generator for Coding Against Interfaces Mainul Islam, Christoph Csallner Software Engineering Research Center (SERC) Computer.
SSQSA present and future Gordana Rakić, Zoran Budimac Department of Mathematics and Informatics Faculty of Sciences University of Novi Sad
1 Exposing Behavioral Differences in Cross-Language API Mapping Relations Hao Zhong Suresh Thummalapenta Tao Xie Institute of Software, CAS, China IBM.
Using Symbolic PathFinder at NASA Corina Pãsãreanu Carnegie Mellon/NASA Ames.
Model Counting with Applications to CodeHunt Willem Visser Stellenbosch University South Africa.
SOFTWARE TESTING. Introduction Software Testing is the process of executing a program or system with the intent of finding errors. It involves any activity.
CAPP: Change-Aware Preemption Prioritization Vilas Jagannath, Qingzhou Luo, Darko Marinov Sep 6 th 2011.
Software Quality Assurance and Testing Fazal Rehman Shamil.
CUTE: A Concolic Unit Testing Engine for C Koushik SenDarko MarinovGul Agha University of Illinois Urbana-Champaign.
( = “unknown yet”) Our novel symbolic execution framework: - extends model checking to programs that have complex inputs with unbounded (very large) data.
Onlinedeeneislam.blogspot.com1 Design and Analysis of Algorithms Slide # 1 Download From
CS527 Topics in Software Engineering (Software Testing and Analysis) Darko Marinov September 7, 2010.
Random Test Generation of Unit Tests: Randoop Experience
Symstra: A Framework for Generating Object-Oriented Unit Tests using Symbolic Execution Tao Xie, Darko Marinov, Wolfram Schulte, and David Notkin University.
Finding bugs with a constraint solver daniel jackson. mandana vaziri mit laboratory for computer science issta 2000.
ECE 750 Topic 8 Meta-programming languages, systems, and applications Automatic Program Specialization for J ava – U. P. Schultz, J. L. Lawall, C. Consel.
Detecting Assumptions on Deterministic Implementations of Non-deterministic Specifications August Shi, Alex Gyori, Owolabi Legunsen, Darko Marinov 4/12/2016.
SOFTWARE TESTING LECTURE 9. OBSERVATIONS ABOUT TESTING “ Testing is the process of executing a program with the intention of finding errors. ” – Myers.
On Combining Multi-formalism Knowledge to Select Models for Model Transformation Testing Sagar Sen (1 st year PhD student), Benoit Baudry, Jean-Marie Mottu.
Cs498dm Software Testing Darko Marinov January 24, 2012.
The PLA Model: On the Combination of Product-Line Analyses 강태준.
Generating Automated Tests from Behavior Models
Input Space Partition Testing CS 4501 / 6501 Software Testing
Chapter 8 – Software Testing
Counterexample Generation for Verification of Object-Oriented Software
All You Ever Wanted to Know About Dynamic Taint Analysis & Forward Symbolic Execution (but might have been afraid to ask) Edward J. Schwartz, Thanassis.
CUTE: A Concolic Unit Testing Engine for C
Presentation transcript:

Systematic Software Testing Using Test Abstractions Darko Marinov RIO Summer School Rio Cuarto, Argentina February 2011

Examples of Structurally Complex Data T1 A1 T2 A2 XML document web sites s1 s2 s4 s3 s red-black tree Java program class A { int f; } class B extends A { void m() { super.f = 0; }

Running Example: Inheritance Graphs Java program interface I { void m(); } interface J { void m(); } class A implements I { void m() {} } class B extends A implements I,J { void m() {} }. IJ A B Inheritance graph Properties 1. DAG 2. ValidJava

Testing Setup Examples of code under test  Compiler or refactoring engines, input: programs  Abstract data type, input/output: data structure  Web traversal code, input: web topology  XML processing code, input/output: XML document code test generation test oracle pass fail inputsoutputs

Test Generation tool code inputs Fully automaticManual inputs tool Semi automated input set description inputs

Test Abstractions Each test abstraction describes a set of (structurally complex) test inputs  Example: inheritance graphs with up to N nodes Workflow  Tester manually writes test abstractions  Tool automatically generates test inputs Benefits  No need to manually write large number of test inputs  Useful for test generation, maintenance, and reuse

Key Questions for Test Abstractions tool test abstraction inputs 1. Which test inputs to generate? 2. What language to use for test abstractions? 3. How to generate test inputs from abstractions? 4. How to check test outputs? 5. How to map failures to faults?

Which Inputs to Generate? Bounded-exhaustive testing  Generate all inputs within given (small) bounds  Rationale: small-scope hypothesis [Jackson & Damon ISSTA’96] Found bugs in both academia and industry  Java compilers, model checkers… [Gligoric et al. ICSE’10]  Refactoring engines in Eclipse/NetBeans [Daniel et al. FSE’07]  Web traversal code from Google [Misailovic et al. FSE’07]  XPath compiler at Microsoft [Stobie ENTCS’05]  Fault-tree analyzer for NASA [Sullivan et al. ISSTA’04]  Constraint solver, network protocol [Khurshid & Marinov J-ASE’04]

How to Describe/Generate Inputs? Filtering test abstractions [SOFTMC’01, ASE’01, FME’02, ISSTA’02, OOPSLA’02, SAT’03, MIT-TR’03, J-ASE’04, SAT’05, LDTA’06, ALLOY’06, ICSE-DEMO’07, STEP’07, FSE’07, ISSTA’08, ICST’09, CSTVA’10] search input s filters bounds  Testers describe what properties test inputs satisfy  Tool: search Generating test abstractions [FSE’07, FASE’09] execute input s generators bounds  Testers describe how to generate test inputs  Tool: execution

Previously Explored Separately filtersgenerators Inheritance graph DAGX  ValidJava  X Other Java properties property 3  X ……… property NX  Some properties easier/harder as filters/generators Key challenge for combining: search vs. execution

UDITA: Combined Both [ICSE’10] filtersgenerators Inheritance graph DAGX  ValidJava  X Other Java properties property 3  X ……… property NX  Extends Java with non-deterministic choices Found bugs in Eclipse/NetBeans/javac/JPF/UDITA

Outline Introduction Example Filtering Test Abstractions Generating Test Abstractions UDITA: Combined Filtering and Generating Evaluation Conclusions

Example: Inheritance Graphs class IG { Node[ ] nodes; int size; static class Node { Node[ ] supertypes; boolean isClass; } Properties DAG  Nodes in the graph should have no direct cycle ValidJava  Each class has at most one superclass  All supertypes of interfaces are interfaces

Example Valid Inheritance Graphs IJ A B G2 C G1 G3 A CB G4 C D J IJ ABC G5

Example Invalid Inheritance Graphs I A B G2 C G1 G3 A CB G4 C J IJ ABC G5 J cycle D class implements class class extends two classes interface extends class class extends interface

(In)valid Inputs Valid inputs = desired inputs  Inputs on which tester wants to test code  Code may produce a regular output or an exception  E.g. for Java compiler Interesting (il)legal Java programs No precondition, input can be any text  E.g. for abstract data types Encapsulated data structure representations Inputs need to satisfy invariants Invalid inputs = undesired inputs

Outline Introduction Example Filtering Test Abstractions Generating Test Abstractions UDITA: Combined Filtering and Generating Evaluation Conclusions

Filtering Test Abstractions Tool requires:  Filters: encode what properties inputs satisfy  Bounds Tool provides:  All inputs within bounds that satisfy the properties search input s filters bounds

Language for Filters Each filter takes an input that can be valid or invalid  Returns a boolean indicating validity Experience from academia and industry showed that using a new language makes adoption hard Write filters in standard implementation language (Java, C#, C++…)  Advantages Familiar language Existing development tools Filters may be already present in code  Challenge: generate inputs from imperative filters

Example Filter: DAG Property boolean isDAG(IG ig) { Set visited = new HashSet (); Set path = new HashSet (); if (ig.nodes == null || ig.size != ig.nodes.length) return false; for (Node n : ig.nodes) if (!visited.contains(n)) if (!isAcyclic(n, path, visited)) return false; return true; } boolean isAcyclic(Node node, Set path, Set visited) { if (path.contains(node)) return false; path.add(node); visited.add(node); for (int i = 0; i < supertypes.length; i++) { Node s = supertypes[i]; for (int j = 0; j < i; j++) if (s == supertypes[j]) return false; if (!isAcyclic(s, path, visited)) return false; } path.remove(node); return true; }

Input Space All possible object graphs with an IG root (obeying type declarations)  Natural input spaces relatively easy to enumerate  Sparse: # valid test inputs << # all object graphs

Bounded-Exhaustive Generation Finite (small) bounds for input space  Number of objects  Values of fields Generate all valid inputs within given bounds  Eliminates systematic bias  Finds all bugs detectable within bounds Avoid equivalent (isomorphic) inputs  Reduces the number of inputs  Preserves capability to find all bugs

Example Bounds Specify number of objects for each class  1 object for IG: { IG 0 }  3 objects for Node: { N 0, N 1, N 2 } Specify set of values for each field  For size: { 0, 1, 2, 3 }  For supertypes[i]: { null, N 0, N 1, N 2 }  For isClass: { false, true } Previously written with special library In UDITA: non-deterministic calls for initialization

Bounds Encoded in UDITA IG initialize(int N) { IG ig = new IG(); ig.size = N; ObjectPool pool = new ObjectPool (N); ig.nodes = new Node[N]; for (int i = 0; i < N; i++) ig.nodes[i] = pool.getNew(); for (Node n : nodes) { int num = getInt(0, N − 1); n.supertypes = new Node[num]; for (int j = 0; j < num; j++) n.supertypes[j] = pool.getAny(); n.isClass = getBoolean(); } return ig; } Java with a few extensions for non-determinism static void mainFilt(int N) { IG ig = initialize(N); assume(isDAG(ig)); assume(isValidJava(ig)); println(ig); }

IG 0 N0N0 N1N1 N2N2 sizes[0]s[1]isCs[1]s[0]s[1]isCs[0]isC N1N1 N1N1 null 3231 Example Input Space 1 IG object, 3 Node objects: total 14 fields (“nodes” and array length not shown) null N0N0 N1N1 N2N2 N0N0 N1N1 N2N2 false true null N0N0 N1N1 N2N2 N0N0 N1N1 N2N2 false true null N0N0 N1N1 N2N2 N0N0 N1N1 N2N2 false true 4 * (4 * 4 * 2 * 3) 3 > 2 19 inputs, but < 2 5 valid IG 0 N0N0 N1N1 N2N2 sizes[0]s[1]isCs[1]s[0]s[1]isCs[0]isC

Input Generation: Search Naïve “solution”  Enumerate entire (finite) input space, run filter on each input, and generate input if filter returns true  Infeasible for sparse input spaces (#valid << #total)  Must reason about behavior of filters Our previous work proposed a solution  Dynamically monitors execution of filters  Prunes large parts of input space for each execution  Avoids isomorphic inputs

Outline Introduction Example Filtering Test Abstractions Generating Test Abstractions UDITA: Combined Filtering and Generating Evaluation Conclusions

Generating Test Abstractions Tool provides:  Generators: encode how to generate inputs  Bounds Tool requires:  All inputs within bounds (that satisfy the properties) execute input s generators bounds

Example Generator: DAG Property void mainGen(int N) { IG ig = initialize(N); generateDAG(ig); generateValidJava(ig); println(ig); } void generateDAG(IG ig) { for (int i = 0; i < ig.nodes.length; i++) { int num = getInt(0, i); ig.nodes[i].supertypes = new Node[num]; for (int j = 0, k = −1; j < num; j++) { k = getInt(k + 1, i − (num − j)); ig.nodes[i].supertypes[j] = ig.nodes[k]; } N0 N1 N2

Outline Introduction Example Filtering Test Abstractions Generating Test Abstractions UDITA: Combined Filtering and Generating Evaluation Conclusions

Filtering vs. Generating: DAG Property boolean isDAG(IG ig) { Set visited = new HashSet (); Set path = new HashSet (); if (ig.nodes == null || ig.size != ig.nodes.length) return false; for (Node n : ig.nodes) if (!visited.contains(n)) if (!isAcyclic(n, path, visited)) return false; return true; } boolean isAcyclic(Node node, Set path, Set visited) { if (path.contains(node)) return false; path.add(node); visited.add(node); for (int i = 0; i < supertypes.length; i++) { Node s = supertypes[i]; for (int j = 0; j < i; j++) if (s == supertypes[j]) return false; if (!isAcyclic(s, path, visited)) return false; } path.remove(node); return true; } void generateDAG(IG ig) { for (int i = 0; i < ig.nodes.length; i++) { int num = getInt(0, i); ig.nodes[i].supertypes = new Node[num]; for (int j = 0, k = −1; j < num; j++) { k = getInt(k + 1, i − (num − j)); ig.nodes[i].supertypes[j] = ig.nodes[k]; } Filtering arguably harder than generating for DAG  20+ vs. 10 LOC However, the opposite for ValidJava property

UDITA Requirement: Allow Mixing filtersgenerators DAGX  ValidJava  X UDITA input s generators bounds filters

Other Requirements for UDITA Language for test abstractions  Ease of use: naturally encode properties  Expressiveness: encode a wide range of properties  Compositionality: from small to large test abstractions  Familiarity: build on a popular language Algorithms and tools for efficient generation of concrete tests from test abstractions Key challenge: search (filtering) and execution (generating) are different paradigms

UDITA Solution Based on a popular language (Java) extended with non-deterministic choices  Base language allows writing filters for search/filtering and generators for execution/generating  Non-deterministic choices for bounds and enumeration  Non-determinism for primitive values: getInt/Boolean  New language abstraction for objects: ObjectPool class ObjectPool { public ObjectPool (int size, boolean includeNull) {... } public T getAny() {... } public T getNew() {... } }

UDITA Implementation Implemented in Java PathFinder (JPF)  Explicit state model checker from NASA  JVM with backtracking capabilities  Has non-deterministic call: Verify.getInt(int lo, int hi) Default/eager generation too slow Efficient generation by delayed choice execution  Publicly available JPF extension Documentation on UDITA web page

Delayed Choice Execution Postpone choice of values until needed Lightweight symbolic execution  Avoids problems with full blown symbolic execution  Even combined symbolic and concrete execution has problems, especially for complex object graphs Eager int x = getInt(0, N); … y = x; … … = y; // non-copy Delayed int x = Susp(0, N); … y = x; … force(y); … = y; // non-copy non-determinism

Object Pools Eager implementation of getNew/getAny by reduction to (eager) getInt  Simply making getInt delayed does not work because getNew is stateful We developed a novel algorithm for delayed execution of object pools  Gives equivalent results as eager implementation  Polynomial-time algorithm to check satisfiability of getNew/getAny constraints (disequality from a set) Previous work on symbolic execution typically encodes into constraints whose satisfiability is NP-hard (disjunctions)

Outline Introduction Example Filtering Test Abstractions Generating Test Abstractions UDITA: Combined Filtering and Generating Evaluation Conclusions

Evaluation UDITA  Compared Delayed and Eager execution  Compared with a previous Generating approach  Compared with Pex (white-box) Case studies on testing with test abstractions  Some results with filtering test abstractions  Some results with generating test abstractions  Tested refactoring engines in Eclipse and NetBeans, Java compilers, JPF, and UDITA

Eager vs. Delayed.

Generating vs. UDITA: LOC

Generating vs. UDITA: Time

UDITA vs. Pex Compared UDITA with Pex  State-of-the-art symbolic execution engine from MSR  Uses a state-of-the-art constraint solver Comparison on a set of data structures  White-box testing: tool monitors code under test  Finding seeded bugs Result: object pools help Pex to find bugs  Summer internship to include object size in Pex

Some Case Studies with Filtering Filtering test abstractions used at Microsoft Enabled finding numerous bugs in tested apps  XML tools XPath compiler (10 code bugs, test-suite augmentation) Serialization (3 code bugs, changing spec)  Web-service protocols WS-Policy (13 code bugs, 6 problems in informal spec) WS-Routing (1 code bug, 20 problems in informal spec)  Others SSLStream MSN Authentication 

Some Case Studies with Generating Generating test abstractions used to test Eclipse and NetBeans refactoring engines [FSE’07] Eight refactorings: target field, method, or class Wrote about 50 generators Reported 47 bugs  21 in Eclipse: 20 confirmed by developers  26 in NetBeans: 17 confirmed, 3 fixed, 5 duplicates, 1 won't fix  Found more but did not report duplicate or fixed Parts of that work included in NetBeans

Typical Testing Scenario Create a model of test inputs (e.g., Java ASTs) Write filters/generators for valid inputs UDITA generates valid inputs Translate from model to actual inputs (pretty-print) Run on two code bases, compare outputs pass fail =? one code another code T1 A1 T2 A2 T3 A3 T1 T2 UDITA bounds filters/generators pretty printer

Some More Bugs Found Eclipse vs. NetBeans refactoring engines  2 bugs in Eclipse and 2 bugs in NetBeans Sun javac compiler vs. Eclipse Java compiler  2 reports (still unconfirmed) for Sun javac Java PathFinder vs. JVM  6 bugs in JPF (plus 5 more in an older version) UDITA Delayed vs. UDITA Eager  Applying tool on (parts of) itself  1 bug in UDITA (patched since then)

Example Bug Generated program import java.util.List; class A implements B, D { public List m() { List l = null; A a = null; l.add(a.m()); return l; } } interface D { public List m(); } interface B extends C { public List m(); } interface c { public List m(); } Incorrect refactoring import java.util.List; class A implements B, D { public List m() { List > l = null; A a = null; l.add(a.m()); return l; } } interface D { public List m(); } interface B extends C { public List m(); } interface c { public List m(); }

Outline Introduction Example Filtering Test Abstractions Generating Test Abstractions UDITA: Combined Filtering and Generating Evaluation Conclusions

Summary Testing is important for software reliability  Necessary step before (even after) deployment Structurally complex data  Increasingly used in modern systems  Important challenge for software testing Test abstractions  Proposed model for complex test data  Adopted in industry  Used to find bugs in several real-world applications

Benefits & Costs of Test Abstractions Benefits  Test abstractions can find bugs in real code (e.g., at Microsoft or for Eclipse/NetBeans/javac/JPF/UDITA)  Arguably better than manual testing Costs 1. Human time for writing test abstractions (filters or generators) [UDITA, ICSE’10] 2. Machine time for generating/executing/checking tests (human time waiting for the tool) [FASE’09] 3. Human time for inspecting failing tests [FASE’09]

Collaborators from U. of Illinois and other schools  Brett Daniel  Danny Dig  Kely Garcia  Vilas Jagannath  Yun Young Lee Funding  NSF CCF , CNS , CNS  Microsoft gift Credits for Generating TA and UDITA  Milos Gligoric (Belgrade->Illinois)  Tihomir Gvero (Belgrade->EPFL)  Sarfraz Khurshid (UT Austin)  Viktor Kuncak (EPFL)

Test Abstractions Test abstractions  Proposed model for structurally complex test data  Adopted in industry  Used to find bugs in several real-world applications (e.g., at Microsoft, Eclipse/NetBeans/javac/JPF/UDITA) UDITA: latest approach for test abstractions  Easier to write test abstractions  Novel algorithm for faster generation  Publicly available JPF extension