Deja vu JavaZone 2013

Preview:

DESCRIPTION

Bugs in production systems are typically communicated in stack traces. But why don't we communicate in unit tests? This presentation discuss a concrete open source Java framework that allows production systems to communicate bugs as test cases. It will produce deterministic, sand-boxable test cases having identical execution paths as the original run. Using the framework correctly will even make multi-threaded scenarios re-playable.

Citation preview

Replay your productions bugsJavaZone 2013

Mads Enevoldsen, Developer, Jayway

Overview

• Problem Definition

• Tracing

• Reproducablilty

• Threads

• Example Architecture

Part I

Problem Definition

Spot of bother

• Why are errors communicated in stack traces?

• Why are production bugs hunted down by inspecting log files?

• Why can’t we communicate in running code?

Unit test

• Proves how code works

• Deterministic

• Environment agnostic

Execution path

1 public class Example {

2

3 public void foo() {

4 bar();

5 // exception occurs

6 }

7

8 private void bar() {

9 //...

10 }

11 }

Computable?

• Reasoning about code

• Source code vs. running code

Part II

Tracing

Deja Vu

• Open source

• Define trace points in your code

• Serialize traces to unit tests

Example

1 public class Example {

2

3 @Traced

4 public void foo() {

5 bar();

6 //...

7 }

8

9 private void bar() {

10 //...

11 }

12 }

@Traced

• Method annotation

• Define ”lumps” of code to be traced

• Store arguments and method ”pointer”

• No state in objects

Setup

• Install callback

• Trace-mode for tracing @Traced

• Replay-mode for re-running generated traces

Replay

1 public class ExampleTest{

2

3 @Test

4 public void exampletest() throws Throwable {

5 TraceBuilder builder = TraceBuilder.build().

6 setMethod(Example.class);

7

8 builder.run();

9 }

10 }

Part III

Reproducability

@Impure

• Randomized/Non-deterministic

• Environment dependent

• Threading

Rules of the game

• Immutable

• Must be serializable++

Lucky number bug

1 public class AlmostWorking {

2

3 @Traced

4 public void getLucky() {

5 Long value = timeStamp();

6 Long luckyNumber = 2304432 / ( value % 1001 );

7 System.out.println( "My lucky number is: "+luckyNumber);

8 }

9

10 @Impure

11 private Long timeStamp() {

12 return System.nanoTime();

13 }

14 }

Overhead

• Execution overhead in intercepting calls

• Memory overhead in storing ”impure” values

• Immutable overhead

Part IV

Threads

Threads

• Non-deterministic!

• For pure parts it doesn’t matter

@AttachThread

• Includes a thread in a trace

• Trace is not done until trace method is executed...

• ...and all attached threads are done executing

• Impure parts are replayed in same order

Example

1 public class WithThreads {

2

3 private ExecutorService executorService;

4

5 public void initialize() {

6 executorService = Executors.newCachedThreadPool();

7 }

8

9 @Traced

10 public void begin( Integer threads) {

11 initialize();

12 for ( int i=0; i<threads; i++ ) {

13 runInThreadPool(new Runner());

14 }

15 }

16

17 @AttachThread

18 private void runInThreadPool( Runnable runnable ) {

19 executorService.submit(runnable);

20 }

21 }

Part V

Example Architecture

Usecases

• Trace on each ’usecase’

• Usecase becomes a programming concept

Thank you

• https://github.com/madsenevoldsen/dejavu

• http://www.jayway.com/2013/01/09/deja-vu/