A Framework for Testing Concurrent Programs COMP 600 Mathias Ricken Rice University August 27, 2007.

Slides:



Advertisements
Similar presentations
Objects and Classes David Walker CS 320. Advanced Languages advanced programming features –ML data types, exceptions, modules, objects, concurrency,...
Advertisements

Semantics Static semantics Dynamic semantics attribute grammars
A Randomized Dynamic Program Analysis for Detecting Real Deadlocks Koushik Sen CS 265.
Generic programming in Java
ConcJUnit: Unit Testing for Concurrent Programs PPPJ 2009 Mathias Ricken and Robert Cartwright Rice University August 28, 2009.
Atomicity in Multi-Threaded Programs Prachi Tiwari University of California, Santa Cruz CMPS 203 Programming Languages, Fall 2004.
OOP in Java Nelson Padua-Perez Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
CS220 Software Development Lecture: Multi-threading A. O’Riordan, 2009.
29-Jun-15 Java Concurrency. Definitions Parallel processes—two or more Threads are running simultaneously, on different cores (processors), in the same.
OOP in Java Fawzi Emad Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
50.003: Elements of Software Construction Week 5 Basics of Threads.
Copyright © 2003 ProsoftTraining. All rights reserved. Sun Certified Java Programmer Exam Preparation Guide.
Testing Concurrent Programs COMP Production Programming Mathias Ricken Rice University Spring 2009.
Unit Testing & Defensive Programming. F-22 Raptor Fighter.
Unit Testing in Java with an Emphasis on Concurrency Corky Cartwright Rice and Halmstad Universities Summer 2013.
Comparison of OO Programming Languages © Jason Voegele, 2003.
Liang, Introduction to Java Programming, Seventh Edition, (c) 2009 Pearson Education, Inc. All rights reserved Chapter 18 Exception Handling.
CSM-Java Programming-I Spring,2005 Objects and Classes Overview Lesson - 1.
Test-First Java Concurrency for the Classroom SIGCSE 2010 Mathias Ricken and Robert Cartwright Rice University March 12, 2009.
Lecture 2 Foundations and Definitions Processes/Threads.
111 © 2002, Cisco Systems, Inc. All rights reserved.
Exceptions Handling Exceptionally Sticky Problems.
Introduction to Object Oriented Programming CMSC 331.
Java Threads. What is a Thread? A thread can be loosely defined as a separate stream of execution that takes place simultaneously with and independently.
Testing Concurrent Programs, A 7-Minute Jargon-Free Introduction Thesis Writing Seminar Mathias Ricken Rice University February 25, 2010.
ABSTRACT The real world is concurrent. Several things may happen at the same time. Computer systems must increasingly contend with concurrent applications.
1 A Framework for Testing Concurrent Programs PhD Thesis Defense Mathias Ricken Rice University January 10, 2011.
Optimistic Design 1. Guarded Methods Do something based on the fact that one or more objects have particular states  Make a set of purchases assuming.
(c) University of Washington01-1 CSC 143 Java Programming as Modeling Reading: Ch. 1-6.
COMP 111 Threads and concurrency Sept 28, Tufts University Computer Science2 Who is this guy? I am not Prof. Couch Obvious? Sam Guyer New assistant.
A Framework for Testing Concurrent Programs MS Thesis Defense Mathias Ricken Rice University June 14, 2007.
Programming in Java CSCI-2220 Object Oriented Programming.
ICS 313: Programming Language Theory Chapter 13: Concurrency.
Chapter 14 Abstract Classes and Interfaces. Abstract Classes An abstract class extracts common features and functionality of a family of objects An abstract.
Java 3: Odds & Ends Advanced Programming Techniques.
JUnit A framework which provides hooks for easy testing of your Java code, as it's built Note: The examples from these slides can be found in ~kschmidt/public_html/CS265/Labs/Java/Junit.
Testing OO software. State Based Testing State machine: implementation-independent specification (model) of the dynamic behaviour of the system State:
David Streader Computer Science Victoria University of Wellington Copyright: David Streader, Victoria University of Wellington Debugging COMP T1.
Multithreaded programming  Java provides built-in support for multithreaded programming. A multithreaded program contains two or more parts that can run.
 In the java programming language, a keyword is one of 50 reserved words which have a predefined meaning in the language; because of this,
Parallel Processing (CS526) Spring 2012(Week 8).  Shared Memory Architecture  Shared Memory Programming & PLs  Java Threads  Preparing the Environment.
CS533 – Spring Jeanie M. Schwenk Experiences and Processes and Monitors with Mesa What is Mesa? “Mesa is a strongly typed, block structured programming.
PROGRAMMING TESTING B MODULE 2: SOFTWARE SYSTEMS 22 NOVEMBER 2013.
1 A Framework for Testing Concurrent Programs PhD Proposal Mathias Ricken Rice University December 2, 2010.
PROGRAMMING PRE- AND POSTCONDITIONS, INVARIANTS AND METHOD CONTRACTS B MODULE 2: SOFTWARE SYSTEMS 13 NOVEMBER 2013.
Classes, Interfaces and Packages
CSSE501 Object-Oriented Development. Chapter 10: Subclasses and Subtypes  In this chapter we will explore the relationships between the two concepts.
ConcJUnit: Unit Testing for Concurrent Programs COMP 600 Mathias Ricken Rice University August 24, 2009.
Object orientation and Packaging in Java Object Orientation and Packaging Introduction: After completing this chapter, you will be able to identify.
3/12/2013Computer Engg, IIT(BHU)1 OpenMP-1. OpenMP is a portable, multiprocessing API for shared memory computers OpenMP is not a “language” Instead,
David Evans CS201j: Engineering Software University of Virginia Computer Science Lecture 10: Programming Exceptionally.
Concurrency (Threads) Threads allow you to do tasks in parallel. In an unthreaded program, you code is executed procedurally from start to finish. In a.
Concurrency in Java MD. ANISUR RAHMAN. slide 2 Concurrency  Multiprogramming  Single processor runs several programs at the same time  Each program.
Concurrent Programming in Java Based on Notes by J. Johns (based on Java in a Nutshell, Learning Java) Also Java Tutorial, Concurrent Programming in Java.
Notices Assn 2 is due tomorrow, 7pm. Moodle quiz next week – written in the lab as before. Everything up to and including today’s lecture: Big Topics are.
Java Thread Programming
Inheritance Modern object-oriented (OO) programming languages provide 3 capabilities: encapsulation inheritance polymorphism which can improve the design,
Healing Data Races On-The-Fly
Inheritance and Polymorphism
Java Programming Language
Accessible Formal Methods A Study of the Java Modeling Language
Generic programming in Java
Multithreading.
Multithreaded Programming
21 Threads.
CS 240 – Advanced Programming Concepts
Foundations and Definitions
Java Annotations for Invariant Specification
Exception Handling.
Testing Concurrent Programs
Presentation transcript:

A Framework for Testing Concurrent Programs COMP 600 Mathias Ricken Rice University August 27, 2007

Unit Testing Program ? Difficult Sub- program Sub- program Sub- program ??? Less difficultEven less difficult ?

Unit Testing Unit tests… –Test a part, not the whole program –Occur earlier –Automate testing –Keep the shared repository clean –Serve as documentation –Prevent bugs from reoccurring Effective with a single thread of control

Foundation of Unit Testing Unit tests depend on deterministic behavior Known input, expected output… Success  correct behavior Failure  flawed code Outcome of test is meaningful

Problems Due to Concurrency Thread scheduling is nondeterministic and machine-dependent –Code may be executed under different schedules –Different schedules may produce different results Known input, expected output… Success  correct behavior in this schedule, may be flawed in other schedule Failure  flawed code Success of unit test is meaningless

Timeliness of the Problem Many programs already use concurrency –Often hidden, as part of GUI Most speed increases are due to multiple cores on one chip –Clock speeds have not increased much Increased use of concurrency in the future

Possible Solutions Programming Language Features –Ensuring that bad things cannot happen –May restrict programmers Lock-Free Algorithms –Ensuring that if bad things happen, it’s ok –May limit data structures available Comprehensive Testing –Testing if bad things happen in any schedule –Does not prevent problems, but does not limit solutions either details

Tractability of Comprehensive Testing Deciding whether any given program contains an error is undecidable –Reduction to the halting problem Does not imply undecidable for all programs

Number of Schedules Test all possible schedules –Concurrent unit tests meaningful again Number of schedules (N) –t: # of threads, s: # of slices per thread Exponential in both s and t details

Critical Points If program is race-free, we do not have to simulate all thread switches –Threads interfere only at “critical points”: lock operations, volatile variables, etc. –Code between critical points cannot affect outcome –Simulate all possible arrangements of blocks delimited by critical points

Critical Points Example Thread 1 Thread 2 Local Var 1 Shared Var Lock lock access unlock All accesses protected by lock Local variables don’t need locking All accesses protected by lock

Fewer Schedules Fewer critical points than thread switches –Reduces number of schedules –Example:Two threads, but no communication  only one schedule required Unit tests are small –Reduces number of schedules Hopefully comprehensive simulation is tractable –If not, heuristics are still better than nothing

Parts of the Framework Improvements to JUnit –Detect exceptions and failed assertions in threads other than the main thread Annotations for Concurrency Invariants –Express complicated requirements about locks and threads Tools for Schedule-Based Execution –Record, deadlock monitor –Random delays, random yields

Concurrency Invariants Has to be called in event thread –TableModel, TreeModel May not be called in event thread –invokeAndWait() Have to acquire readers/writers lock –AbstractDocument –DrJava’s documents

Invariants Difficult to Determine May be found in –Javadoc comments –Only in internal comments –Whitepapers Often not documented at all Errors not immediately evident Impossible to check automatically

Java Annotations Add invariants as public static void invokeAndWait( Runnable r) { … } Process class files –Find uses of annotations –Insert bytecode to check invariants at method beginning

Advantages of Annotations Java Language constructs –Syntax checked by compiler Easy to apply to part of the program –e.g. when compared to a type system change Light-weight –Negligible runtime impact if not debugging (slightly bigger class files) Automated Checking

Predicate Annotations In annotation definition, specify static boolean Java method –Method must be callable from every context  completely static and public Data in annotation, method arguments and value of this passed when method invoked

Predicate Annotation Example public class public void test(String param){…} public void test(String param){…}}… TestCode t = new TestCode(); value=Predicates.class, value=Predicates.class, method="example", method="example", arguments=true) arguments=true) TestAllowed { boolean allowed; boolean allowed;} public class Predicates { public static boolean example( public static boolean example( Object this0, Object this0, String param, String param, boolean allowed) { boolean allowed) { return (allowed)? // this0==t return (allowed)? // this0==t (param.equals("test")): // param=="xxx" (param.equals("test")): // param=="xxx" (!param.equals("test")); // allowed==true (!param.equals("test")); // allowed==true} zoom

Provided Annotations Inverses, conjunctions, disjunctions

Invariant Inheritance Invariants apply to the method and all overriding methods in subclasses  Methods can have invariants defined elsewhere All annotations describe requirements for the client (and, due to subclassing, for subclasses) –Allows frameworks to describe requirements

Invariant Subtyping To maintain substitutability, subclasses may not strengthen invariants Invariants can be modeled as special input parameter –Tuple of invariants (“record” in λ calculus [Pierce]) –Subtyping rules for records declare the “wider” record as subtype –In function types, parameter types are contravariant

Invariant Subtyping Analyze methods with invariants Invariants subtyping: A B C I A = {}, I B = {inv 1 }, I C = {inv 1,inv 2 }; I C <: I B <: I A F A = I A → ·, F B = I B → ·, F C = I C → ·; F A <: F B <: F C Java subtyping: C <: B <: A class A { void f() void f() { … }; { … };} class B extends A { extends void f() void f() { … }; { … };} class C extends B { extends void f() void f() { … }; { … };}

Detection of Subtyping Problems If Java subtyping and invariant subtyping disagree (A <: B but B A) –Substitutability not maintained –Statically emit warning Detect if client subclasses do not use framework classes as prescribed –Safer multithreaded frameworks

Java API Annotations Started to annotate methods in Java API Community project at –Browse and suggest annotations Annotations can be extracted into XML –Share annotations –Add checks without needing source code

Testing Invariant Checker Annotated two DrJava versions –3/26/2004 –9/2/2006 Ran test suite, logged invariant violations –2004: 18.83% failed –2006: 11.03% failed 2006 version easier to annotate –Better documentation of invariants details

Conclusion Improved JUnit now detects problems in other threads Annotations ease documentation and checking of concurrency invariants Support programs for schedule-based execution

Future Work Schedule-Based Execution –Replay given schedule –Generate possible schedules –Dynamic race detection –Probabilities/durations for random yields/sleeps Extend annotations to Floyd-Hoare logic –Preconditions, postconditions –Representation invariants

Many Thanks To… My advisor –Corky Cartwright My committee members –Walid Taha –Bill Scherer My friends –JavaPLT, CS and Rice NFS and Texas ATP –For partially providing funding

Extra Slides

Possible Solutions Programming Language Features –Race Freedom –Deadlock Freedom, Safe Locking –Atomicity, Transactions –Usually require changes in type system –Fundamental change C++ standards: 1998, 2003, 200x Java major changes: 1997 (1.0), 2002 (1.4), 2004 (1.5) back

Possible Solutions Lock-Free Algorithms –Work on copy and assume no concurrency is present (or current thread will finish first) –If there was interference, threads that don’t finish first redo their work –Require some system support (e.g. compare- and-swap), then done in libraries –Not all common data structures are practical and efficient to implement as lock-free back

Extra: Number of Schedules back Product of s-combinations For thread 1: choose s out of ts time slices For thread 2: choose s out of ts-s time slices … For thread t-1: choose s out of 2s time slices For thread t-1: choose s out of s time slices Writing s-combinations using factorial Cancel out terms in denominator and next numerator Left with (ts)! in numerator and t numerators with s!

Improvements to JUnit Uncaught exceptions and failed assertions –Not caught in child threads

Sample JUnit Tests public class Test extends TestCase { public void testException() { public void testException() { throw new RuntimeException("booh!"); throw new RuntimeException("booh!"); } public void testAssertion() { public void testAssertion() { assertEquals(0, 1); assertEquals(0, 1); }} if (0!=1) throw new AssertionFailedError(); } Both tests fail.

Problematic JUnit Tests public class Test extends TestCase { public void testException() { public void testException() { new Thread(new Runnable() { new Thread(new Runnable() { public void run() { public void run() { throw new RuntimeException("booh!"); throw new RuntimeException("booh!"); } }).start(); }).start(); }} new Thread(new Runnable() { public void run() { public void run() { throw new RuntimeException("booh!"); throw new RuntimeException("booh!"); }}).start(); throw new RuntimeException("booh!"); Main thread Child thread Main thread Child thread spawns uncaught! end of test success!

Problematic JUnit Tests public class Test extends TestCase { public void testException() { public void testException() { new Thread(new Runnable() { new Thread(new Runnable() { public void run() { public void run() { throw new RuntimeException("booh!"); throw new RuntimeException("booh!"); } }).start(); }).start(); }} new Thread(new Runnable() { public void run() { public void run() { throw new RuntimeException("booh!"); throw new RuntimeException("booh!"); }}).start(); throw new RuntimeException("booh!"); Main thread Child thread Uncaught exception, test should fail but does not!

Improvements to JUnit Uncaught exceptions and failed assertions –Not caught in child threads Thread group with exception handler –JUnit test runs in a separate thread, not main thread –Child threads are created in same thread group –When test ends, check if handler was invoked

Thread Group for JUnit Tests public class Test extends TestCase { public void testException() { public void testException() { new Thread(new Runnable() { new Thread(new Runnable() { public void run() { public void run() { throw new RuntimeException("booh!"); throw new RuntimeException("booh!"); } }).start(); }).start(); }} new Thread(new Runnable() { public void run() { public void run() { throw new RuntimeException("booh!"); throw new RuntimeException("booh!"); }}).start(); throw new RuntimeException("booh!"); Test thread Child thread invokes checks TestGroup’s Uncaught Exception Handler

Thread Group for JUnit Tests public class Test extends TestCase { public void testException() { public void testException() { new Thread(new Runnable() { new Thread(new Runnable() { public void run() { public void run() { throw new RuntimeException("booh!"); throw new RuntimeException("booh!"); } }).start(); }).start(); }} new Thread(new Runnable() { public void run() { public void run() { throw new RuntimeException("booh!"); throw new RuntimeException("booh!"); }}).start(); throw new RuntimeException("booh!"); Test thread Child thread Test thread Child thread spawns uncaught! end of test failure! invokes group’s handler Main thread spawns and waitsresumes check group’s handler

Improvements to JUnit Uncaught exceptions and failed assertions –Not caught in child threads Thread group with exception handler –JUnit test runs in a separate thread, not main thread –Child threads are created in same thread group –When test ends, check if handler was invoked Detection of uncaught exceptions and failed assertions in child threads that occurred before test’s end

Child Thread Outlives Parent public class Test extends TestCase { public void testException() { public void testException() { new Thread(new Runnable() { new Thread(new Runnable() { public void run() { public void run() { throw new RuntimeException("booh!"); throw new RuntimeException("booh!"); } }).start(); }).start(); }} new Thread(new Runnable() { public void run() { public void run() { throw new RuntimeException("booh!"); throw new RuntimeException("booh!"); }}).start(); throw new RuntimeException("booh!"); Test thread Child thread Test thread Child thread spawns uncaught! end of test failure! invokes group’s handler Main thread spawns and waitsresumes check group’s handler

Child Thread Outlives Parent public class Test extends TestCase { public void testException() { public void testException() { new Thread(new Runnable() { new Thread(new Runnable() { public void run() { public void run() { throw new RuntimeException("booh!"); throw new RuntimeException("booh!"); } }).start(); }).start(); }} new Thread(new Runnable() { public void run() { public void run() { throw new RuntimeException("booh!"); throw new RuntimeException("booh!"); }}).start(); throw new RuntimeException("booh!"); Test thread Child thread Test thread Child thread spawns uncaught! end of test success! invokes group’s handler Main thread spawns and waitsresumes check group’s handler Too late!

Improvements to JUnit Child threads are not required to terminate –A test may pass before an error is reached Detect if any child threads are still alive –Declare failure if test thread has not waited –Ignore daemon threads, system threads (AWT, RMI, garbage collection, etc.) Previous schedule is a test failure –Should be prevented by using Thread.join()

Testing ConcJUnit Replacement for junit.jar or as plugin JAR for JUnit 4.2 Available as binary and source at Results from DrJava’s unit tests –Child thread for communication with slave VM still alive in test –Several reader and writer threads still alive in low level test (calls to join() missing)

Limitations Improvements only check chosen schedule –A different schedule may still fail –Requires comprehensive testing to be meaningful May still miss uncaught exceptions –Specify absolute parent thread group, not relative Cannot detect uncaught exceptions in a program’s uncaught exception handler (JLS limitation) details

Extra: Limitations May still miss uncaught exceptions –Specify absolute parent thread group, not relative (rare) Koders.com: 913 matches ThreadGroup vs. 49,329 matches for Thread –Cannot detect uncaught exceptions in a program’s uncaught exception handler (JLS limitation) Koders.com: 32 method definitions for uncaughtException method back

Generic Annotations? as generic annotation? And { T[] terms(); T[] terms();} OnlyThreadWithName { String name(); String name();} Generics not allowed in annotations

Extra: DrJava Statistics %1071 Unit tests passedfailed not run Invariantsmetfailed % failed KLOC “event thread” back

Predicate Annotation method="example", method="example", arguments=true) arguments=true) TestAllowed { boolean allowed; boolean allowed;} Definition Refers to Predicates.example back

Predicate Annotation Example public class public void test(String param) { … } public void test(String param) { … }}… TestCode t = new TestCode(); t.test("xxx"); Usage Call back

Predicate Annotation Example public class Predicates { public static boolean example( public static boolean example( Object this0, Object this0, String param, String param, boolean allowed) { boolean allowed) { return (allowed)? (param.equals("test")): return (allowed)? (param.equals("test")): (!param.equals("test")); (!param.equals("test"));} back Predicate Method

back Predicate Annotation Example

Problem: Multiple Annotations Java does not allow the same annotation class // error void testMethod() { … } Conjunctions, disjunctions and negations?

Annotation Subclasses? Let annotation extend a supertype? Invariant { } OnlyThreadWithName extends Invariant { String name(); } extends Invariant { String name(); } And extends Invariant { Invariant[] terms(); Invariant[] terms();} Subtyping not allowed for annotations

Work-Around SeveralNames { OnlyThreadWithName[] void testMethod() { … }

Combine Annotations May only contain invariant annotations –Predicate annotations –Combine annotations –Arrays of the above Predicate method automatically generated –Calls member predicate methods –Performs AND, OR, XOR, NOT or IMPLIES

Invariants As Class Annotation Short-hand for annotating all methods What about methods already introduced in a super class, e.g. Object.notify() ? What about methods introduced in class A { void foo() { … } void foo() { … } void bar() { … } void bar() { … }} class void foo() { … } void foo() { void bar() { … } void bar() { … }}

Invariants As Class Annotation Apply invariants on a class only to methods introduced in the class or subclasses class A { public void foo() { … } public void foo() { … // only applies to // only applies to bar() class B extends A { class B extends A { public void bar() { … } public void bar() { … }}

Bytecode Rewriting Except for JUnit, all tools use bytecode rewriting –Class files easier to parse than source –Works for classes without source (Java API) –Can perform changes on-the-fly Adding code to detect properties –“instrumentation” Offline and on-the-fly –Offline:Class file  class file tool –On-the-fly: Custom class loader

Local vs. Global Changes can be done by –modifying one method (local) –all code that calls the method (global) Local instrumentation usually better –Fewer changes, less bytecode –Harder to make a partial instrumentation if global Not all instrumentations can be done locally –If method is native, no class file exists

Other Contributions Recording schedules –thread ID/type –thread ID/type/object ID/class/method/PC Deadlock detector –thread ID/type/object ID recording required –Creates wait graph for each thread and lock –Cycle in graph implies deadlock

Random Sleeps/Yields Randomly insert sleeps or yield before or after critical points Example: If a notify() is delayed, a wait() may time out. Can detect a number of sample problems Have not studied probabilities or durations for sleeps/yields –One inserted delay may negatively impact a second inserted delay Example: If both notify() and wait() are delayed.