272: Software Engineering Fall 2012 Instructor: Tevfik Bultan Lecture 8: Semi-automated test generation via UDITA.

Slides:



Advertisements
Similar presentations
Chapter 14 Software Testing Techniques - Testing fundamentals - White-box testing - Black-box testing - Object-oriented testing methods (Source: Pressman,
Advertisements

Abstraction of Source Code (from Bandera lectures and talks)
Korat Automated Testing Based on Java Predicates Chandrasekhar Boyapati, Sarfraz Khurshid, Darko Marinov MIT ISSTA 2002 Rome, Italy.
Representing Boolean Functions for Symbolic Model Checking Supratik Chakraborty IIT Bombay.
Semantics Static semantics Dynamic semantics attribute grammars
Masahiro Fujita Yoshihisa Kojima University of Tokyo May 2, 2008
A System to Generate Test Data and Symbolically Execute Programs Lori A. Clarke September 1976.
Partial Order Reduction: Main Idea
Introducing Formal Methods, Module 1, Version 1.1, Oct., Formal Specification and Analytical Verification L 5.
Compilation 2011 Static Analysis Johnni Winther Michael I. Schwartzbach Aarhus University.
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.
Expressions and Statements. 2 Contents Side effects: expressions and statements Expression notations Expression evaluation orders Conditional statements.
CS 267: Automated Verification Lecture 10: Nested Depth First Search, Counter- Example Generation Revisited, Bit-State Hashing, On-The-Fly Model Checking.
Algorithm Strategies Nelson Padua-Perez Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
1 CS2200 Software Development Lecture: Testing and Design A. O’Riordan, 2008 K. Brown,
CSE503: SOFTWARE ENGINEERING SYMBOLIC TESTING, AUTOMATED TEST GENERATION … AND MORE! David Notkin Spring 2011.
Chapter 7Louden, Programming Languages1 Chapter 7 - Control I: Expressions and Statements "Control" is the general study of the semantics of execution.
Lecture 27 Exam outline Boxing of primitive types in Java 1.5 Generic types in Java 1.5.
CS 290C: Formal Models for Web Software Lecture 10: Language Based Modeling and Analysis of Navigation Errors Instructor: Tevfik Bultan.
Michael Ernst, page 1 Improving Test Suites via Operational Abstraction Michael Ernst MIT Lab for Computer Science Joint.
Efficient Modular Glass Box Software Model Checking Michael Roberson Chandrasekhar Boyapati The University of Michigan.
Chapter 7Louden, Programming Languages1 Chapter 7 - Control I: Expressions and Statements "Control" is the general study of the semantics of execution.
Introduction to Software Design Chapter 1. Chapter 1: Introduction to Software Design2 Chapter Objectives To become familiar with the software challenge.
1/23/2003University of Virginia1 Korat: Automated Testing Based on Java Predicates CS751 Presentation by Radu Stoleru C.Boyapaty, S.Khurshid, D.Marinov.
Korat: Automated Testing Based on Java Predicates Chandrasekhar Boyapati 1, Sarfraz Khurshid 2, and Darko Marinov 3 1 University of Michigan Ann Arbor.
272: Software Engineering Fall 2012 Instructor: Tevfik Bultan Lecture 4: SMT-based Bounded Model Checking of Concurrent Software.
Software Testing Sudipto Ghosh CS 406 Fall 99 November 9, 1999.
Language Evaluation Criteria
Reverse Engineering State Machines by Interactive Grammar Inference Neil Walkinshaw, Kirill Bogdanov, Mike Holcombe, Sarah Salahuddin.
CUTE: A Concolic Unit Testing Engine for C Technical Report Koushik SenDarko MarinovGul Agha University of Illinois Urbana-Champaign.
1/20 Symbolic Execution and Program Testing Charngki PSWLAB Symbolic Execution and Program Testing James C.King IBM Thomas J.Watson Research Center.
Systematic Software Testing Using Test Abstractions Darko Marinov RIO Summer School Rio Cuarto, Argentina February 2011.
Korat: Automated Testing Based on Java Predicates
A Specification Language and Test Planner for Software Testing Aolat A. Adedeji 1 Mary Lou Soffa 1 1 DEPARTMENT OF COMPUTER SCIENCE, UNIVERSITY OF VIRGINIA.
272: Software Engineering Fall 2012 Instructor: Tevfik Bultan Lecture 6: Exhaustive Bounded Testing and Feedback-Directed Random Testing.
Dynamic Analysis of Multithreaded Java Programs Dr. Abhik Roychoudhury National University of Singapore.
CMP-MX21: Lecture 4 Selections Steve Hordley. Overview 1. The if-else selection in JAVA 2. More useful JAVA operators 4. Other selection constructs in.
Symbolic Execution with Abstract Subsumption Checking Saswat Anand College of Computing, Georgia Institute of Technology Corina Păsăreanu QSS, NASA Ames.
jFuzz – Java based Whitebox Fuzzing
Learning Symbolic Interfaces of Software Components Zvonimir Rakamarić.
Declarative Programming in Java using JSetL E. PanegaiG. Rossi Dipartimento di Matematica Università di Parma Roma, Giugno 2005 Convegno Italiano.
Symbolic and Concolic Execution of Programs Information Security, CS 526 Omar Chowdhury 10/7/2015Information Security, CS 5261.
White Box Testing Arun Lakhotia University of Southwestern Louisiana P.O. Box Lafayette, LA 70504, USA
Using Symbolic PathFinder at NASA Corina Pãsãreanu Carnegie Mellon/NASA Ames.
272: Software Engineering Fall 2012 Instructor: Tevfik Bultan Lecture 9: Test Generation from Models.
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.
CMPSC 16 Problem Solving with Computers I Spring 2014 Instructor: Tevfik Bultan Lecture 4: Introduction to C: Control Flow.
/ PSWLAB Evidence-Based Analysis and Inferring Preconditions for Bug Detection By D. Brand, M. Buss, V. C. Sreedhar published in ICSM 2007.
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.
Detecting Assumptions on Deterministic Implementations of Non-deterministic Specifications August Shi, Alex Gyori, Owolabi Legunsen, Darko Marinov 4/12/2016.
CS223: Software Engineering Lecture 26: Software Testing.
Software Testing.
Control Flow Testing Handouts
Compilers Principles, Techniques, & Tools Taught by Jing Zhang
Outline of the Chapter Basic Idea Outline of Control Flow Testing
A Test Case + Mock Class Generator for Coding Against Interfaces
Dynamic Symbolic Data Structure Repair
Software Testing (Lecture 11-a)
Scratch: selection / branching/ if / If…else / compound conditionals / error trapping by Mr. Clausen.
Counterexample Generation for Verification of Object-Oriented Software
Coding Concepts (Basics)
Automatic Test Generation SymCrete
UNIT V Run Time Environments.
CUTE: A Concolic Unit Testing Engine for C
Assertions References: internet notes; Bertrand Meyer, Object-Oriented Software Construction; 4/25/2019.
Presentation transcript:

272: Software Engineering Fall 2012 Instructor: Tevfik Bultan Lecture 8: Semi-automated test generation via UDITA

Testing It is widely acknowledged both in academia and industry that testing is crucial Test driven development supported by testing tools such as Junit are very popular in practice However, tools like JUnit automate test execution they do not automate test generation In practice, test generation is still a manual activity We have discussed several novel techniques for automated test generation: –Bounded exhaustive test generation based on class invartiants (Korat) –Random test generation that uses the methods in the program to construct random method sequences in order to generate test cases (Randoop) –Dynamic symbolic execution (aka, concolic execution, CUTE, DART)

A Semi-automated Approach The UDITA approach is a semi-automated approach Let the user specify how the tests should be generated but provide some support for automating the test generation process Basic idea: Allow the user to write a set of test cases using non- deterministic choice operators –During test specification, the user can specify a range of values instead of a particular input value –During automated test generation, each value from that range will be selected UDITA follows the bounded exhaustive testing approach –It allows the user to guide the exhaustive exploration

UDITA Contributions: A language that extends Java with non-deterministic choice primitives Lazy non-deterministic evaluation: During test generation the choices made using the non-deterministic choice primitives are delayed until they are first accessed Implementation of the UDITA approach on top of the JPF model checker Demonstration of the efficiency of the proposed approach by comparing with earlier approaches

Specification of tests Two basic approaches for test generation: Declarative (filtering) style Write predicates which specify what a valid test case is –This is like the repOK methods from the KORAT approach –Write a method that returns true if the input is a valid test case, and false otherwise –Generate all the inputs (within in a bound) for which the method would return true Imperative (generating) style Write generators which construct the test cases –Can use non-determinism to define multiple test cases with one method

UDITA primitives for test generation UDITA provides a set of basic generators (these are the primitives that introduce the non-determinism in the specifications) getInt(int lo, int hi): returns an integer between lo and hi inclusively getBoolean(): returns true or false getNew: returns an object that was not returned by any previous calls and which is not null getAny: returns an object from the object pool (and optionally null) UDITA provides an assume primitive assume: restricts the generated test cases to only the ones that satisfy the assumption UDITA provides an interface for encapsulating generators: IGenerator interface

Example Java Inheritence Graphs Constraints: DAG (directed acyclic graph): The nodes in the graph should have no directed cycle along the references of supertypes JavaInheritance: All supertypes of an interface are interfaces, and each class has at most one supertype class Goal: Generate Java programs based on Java inheritance graphs to test programs that take Java programs as input (such as compilers, refactoring tools, IDEs etc.) class IG { Node[] nodes; int size; static class Node { Node[] supertypes; boolean isClass; } }

Filtering approach for inheritance graphs 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]; // two supertypes cannot be the same for (int j = 0; j < i; j++) if (s == supertypes[j]) return false; // check property on every supertype of this node if (!isAcyclic(s, path, visited)) return false; } path.remove(node); return true; }

Filtering approach for inheritance graphs boolean isJavaInheritance(IG ig) { for (Node n : ig.nodes) { boolean doesExtend = false; for (Node s : n.supertypes) if (s.isClass) { // interface must not extend any class if (!n.isClass) return false; if (!doesExtend) { doesExtend = true; // class must not extend more than one class } else { return false; } } } }

Generating approach for inheritance graphs void generateDAGBackbone(IG ig) { for (int i = 0; i < ig.nodes.length; i++) { int num = getInt(0, i); // pick number of supertypes ig.nodes[i].supertypes = new Node[num]; for (int j = 0, k = −1; j < num; j++) { k = getInt(k + 1, i − (num − j)); // supertypes of ”i” can be only those ”k” generated before ig.nodes[i].supertypes[j] = ig.nodes[k]; } } } void generateJavaInheritance(IG ig) { // not shown imperatively because it is complex: // topologically sorts ”ig” to find what nodes // can be classes or interfaces }

Bounded exhaustive generation IG initialize(int N) { IG ig = new IG(); ig.size = N; ObjectPoolNode pool = new ObjectPoolNode (N); ig.nodes = new Node[N]; for (int i = 0; i < N; i++) ig.nodes[i] = pool.getNew(); for (Node n : nodes) { // next 3 lines unnecessary when using generateDAGBackbone int num = getInt(0, N − 1); n.supertypes = new Node[num]; for (int j = 0; j < num; j++) n.supertypes[j] = pool.getAny(); // next line unnecessary when using generateJavaInheritance n.isClass = getBoolean(); } return ig; } static void mainFilt(int N) { IG ig = initialize(N); assume(isDAG(ig)); assume(isJavaInheritance(ig)); println(ig); } static void mainGen(int N) { IG ig = initialize(N); generateDAGBackbone(ig); generateJavaInheritance(ig); println(ig); }

Combining declarative and imperative styles In the inheritance graph generation –DAG property is easier to specify using the imperative style –Java inheritance property is easier to specify using the declarative style In an UDITA generator, these styles can be combined This leads to more compact test specifications

Automated test case generation Given the generator specification, UDITA automatically generates test cases using bounded-exhaustive test generation It uses JPF model checker to do this –JPF model checker backtracks on all non-deterministic choices UDITA uses two techniques: –Isomorphism avoidence It achieves this using the approach used in Korat by ordering the generated objects – Delayed execution Postpones the branching in the computation tree generated by the program –Do not make the non-deterministic choice until the generated value is used –There is no reason to execute the statements that do not depend on a non-deterministic value for different choices (since they do not depend on that choice)

Evaluation UDITA performed better than earlier bounded-exhaustive testing approaches –Delaying non-deterministic choices improves the run time exponentially –Test generation using JPF (which stores the visited states) is more efficient than stateless test generation using a standard JVM (which was the case for an earlier tool called ASTGen) UDITA found bugs in Eclipse and Java compilers –Differential testing They generated test cases and ran both compilers to see if the output differed This way they avoid the oracle specification problem, each compiler serves as an oracle to the other compiler UDITA approach is more effective than dynamic symbolic execution for generating test cases that require complex structures (like generating programs as test cases for compilers)