setac: a phased deterministic testing framework for scala...

22
Setac: A Phased Deterministic Testing Framework for Scala Actors Samira Tasharofi Jun 02, 2011 Stanford, CA

Upload: others

Post on 14-Aug-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Setac: A Phased Deterministic Testing Framework for Scala

Actors

Samira TasharofiJun 02, 2011Stanford, CA

Page 2: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Motivation• Schedule is a source of non-determinism in

concurrent programso Shared memory: order of accesses o Message-passing: order of messages

• The output of the program might be different for a given input depending on the schedule

• The bugs may only show up during some specific scheduleso Systematic exploration can lead to state space explosion

7/17/2011Setac Testing Framework 2

Page 3: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Actor Model• Actor is a computational entity with a mail box and

local stateo Deliver a message

• Append the message to the mail boxo Process a message

• Extract a message from the mail box and execute that• Determined by message handler

• In response to a message it processes:o Changes its local stateo Sends messages to other actorso Creates new actors

7/17/2011Setac Testing Framework 3

Page 4: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Actors in Scala• Package scala.actors in Scala library• Developed by Philipp Haller• Features

o Synchronous and asynchronous communicationo Dynamic creation/destroying of actorso Exception handlingo Remote actorso Customization of the thread pool executing actors

7/17/2011Setac Testing Framework 4

Page 5: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Example: BoundedBufferclass BoundedBuffer(maxSize: Int) extends Actor {

var content = new Array[Int](size)var head, tail, curSize = 0startoverride def act() = loop {

react {case Put(x) if (curSize < maxSize) => {

content(tail) = x tail = (tail + 1) % size curSize += 1

}case Get if (curSize > 0) => {

val r = content(head) head = (head + 1) % size curSize -= 1 reply(r)

}}

}}

class Consumer(buf: Actor) extends Actor {var token = -1startoverride def act() = loop {

react {case Consume(count) =>

for (i <- 0 to count-1)token = (buf !? Get).asInstanceOf[Int]

}}

}

class Producer(buf: Actor) extends Actor {start

override def act() = loop {react {

case Produce(values) => values.foreach(v => buf ! Put(v))

}}

}

7/17/2011Setac Testing Framework 5

Page 6: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

BufferTest

7/17/2011Setac Testing Framework 6

buffer(1)

Put(4), Put(5)

Get, Get

producer

consumer 4, 5

class BufferTest {@Testdef testBuffer() {

val buf = new BoundedBuffer(1)val consumer = new Consumer(buf)val producer = new Producer(buf)

producer ! Produce(List(4, 5))consumer ! Consume(2)

// consumer should receive 4 and 5assert(… )

}

Page 7: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Buggy BoundedBufferclass BoundedBuffer(maxSize: Int) extends Actor {

var content = new Array[Int](size)var head, tail, curSize = 0startoverride def act() = loop {

react {case Put(x) if (curSize maxSize) => {

content(tail) = x tail = (tail + 1) % size curSize += 1

}case Get if (curSize > 0) => {

val r = content(head) head = (head + 1) % size curSize -= 1 reply(r)

}}

}}

7/17/2011Setac Testing Framework 7

<=<

Bug

Page 8: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Buggy BoundedBuffer: Schedules in BufferTest

class BoundedBuffer(maxSize: Int) extends Actor {var content = new Array[Int](size)var head, tail, curSize = 0startoverride def act() = loop {

react {case Put(x) if (curSize maxSize) => {

content(tail) = x tail = (tail + 1) % size curSize += 1

}case Get if (curSize > 0) => {

val r = content(head) head = (head + 1) % size curSize -= 1 reply(r)

}}

}}

7/17/2011Setac Testing Framework 8

<=

buffer(1)producerconsumer

Put(4)

Get

Put(5)

Get

5

4

5

5

Error!

Page 9: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Correct BoundedBuffer: Checking Assertions in Test

class BoundedBuffer(maxSize: Int) extends Actor {var content = new Array[Int](size)var head, tail, curSize = 0startoverride def act() = loop {

react {case Put(x) if (curSize < maxSize) => {

content(tail) = x tail = (tail + 1) % size curSize += 1

}case Get if (curSize > 0) => {

val r = content(head) head = (head + 1) % size curSize -= 1 reply(r)

}}

}}

7/17/2011Setac Testing Framework 9

class SimpleBufferTest {@Testdef testBuffer() {

val buf = new BoundedBuffer(1)buf ! Put(4)assert(buf.curSize == 1)

}

bufferPut(4)

…mailbox

content, head, tail,

curSize

local state

assert

Fails!!

Fails!!

Page 10: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Testing Actor Programs• Problems:

o How to write unit tests for Actor programs while controlling the schedule?o How to check assertions at appropriate times?

• Current Solutions:o Using synchronization constructs, e.g. Latches and Barrierso Using Thread.sleep

7/17/2011Setac Testing Framework 10

Page 11: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

BufferTest: A Test ScheduleBoundedeBuffer(1)ProducerConsumer

Check assertionsGet

Put(4)

Put(5)

Get

4

5

Check assertions

Check assertions

Phase 1

Phase 2

Phase 3

7/17/2011 11Setac Testing Framework

Page 12: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Traditional: BufferTestclass BufferTest {

@Testdef testBuffer() {

val putLatch = new CountDownLatch(2)val getLatch = new CountDownLatch(2)val buf = new BoundedBuffer(1, putLatch, getLatch)

val consumeLatch = new CountDownLatch(1)val consumer = new Consumer(buf, consumeLatch)val producer = new Producer(buf)

//Phase 1consumer ! Consume(1)consumeLatch.await()Thread.sleep(1000)assert(consumer.getState == State.Blocked &&

buf.curSize == 0)

// … }

}

class Consumer(buf: Actor, consumeLatch: CountDownLatch) extends Actor {

var token = -1startoverride def act() = loop {

react {case Consume(count) => consumeLatch.countDown()for (i <- 0 to count-1)

token = (buf !? Get).asInstanceOf[Int]}

}}

7/17/2011Setac Testing Framework 12

Phase 1

consumer producer buffer(1)

Get

Page 13: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Traditional: BufferTest (cont)

class BufferTest {@Testdef testBuffer() {// …//Phase 2producer ! Produce(List(4, 5))putLatch.await()assert(consumer.token == 4 && buf.curSize == 1)

// Phase 3consumer ! Consume(1)getLatch.await()assert(consumer.token == 5 && buf.curSize == 0)

}}

class BoundedBuffer(maxSize: Int, putLatch: CountDownLatch, getLatch: CountDownLatch) extends Actor {var content = new Array[Int](size)var head, tail, curSize = 0startoverride def act() = loop {

react {case Put(x) if (curSize < maxSize) => {content(tail) = x tail = (tail + 1) % size curSize += 1putLatch.countDown()

}case Get if (curSize > 0) => {val r = content(head) head = (head + 1) % size curSize -= 1 reply(r)getLatch.countDown()

}}

}}

7/17/2011Setac Testing Framework 13

Phase 2

consumer producer buffer(1)Put(4)

Put(5)

Get

4

5Phase 3

Page 14: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Traditional BufferTestProblems

• Unreliableo Thread.sleep

• Complexity and Deadlock possibilityo Latches and Barriers

• Costlyo Changing the program under test

7/17/2011Setac Testing Framework 14

Page 15: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Setac• Specify tests with some constraints on the schedule

o Partial order of schedule messageso Centralized schedule, less complexity

• Checking assertions when the system is stableo There is no message that can be processedo No progress in the system

• No change in the run time environment

• Minimal changes in the program under test

7/17/2011Setac Testing Framework 15

Page 16: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Setac: BufferTestclass BufferTest extends SetacTest {@Testdef testBuffer() {val buf = new BoundedBuffer(1)val consumer = new Consumer(buf)val producer = new Producer(buf)val put4 = createScheduleMessage(producer, buf, Put(4))val put5 = createScheduleMessage(producer, buf, Put(5))val gets = createMultipleScheduleMessage(2, consumer, buf, Get)

producer ! Produce(List(4, 5))consumer ! Consume(2)

//Phase 1setSchedule(gets(0))assertWhenStable(consumer.isBlocked && buf.curSize == 0)

//Phase 2setSchedule(put4 -> put5)assertWhenStable(consumer.token == 4 && buf.curSize == 1 && put5.isProcessed)

// Phase 3setSchedule(gets(1))assertWhenStable(consumer.token == 5 && buf.curSize == 0)

}}

7/17/2011Setac Testing Framework 16

Page 17: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Setac: BufferTest (cont)class BoundedBuffer(size: Int) extends Actor {

// …}

class Consumer(buf: Actor) extends Actor {

// …}

class Producer(buf: Actor) extends Actor {

// …}

7/17/2011Setac Testing Framework 17

TestActor {

TestActor {

TestActor {

Page 18: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Setac: BufferTest• Removed Thread.sleep

o More reliable

• Removed synchronization constructs, e.g. Latcheso Reduced complexity

• Minimized changes in the program under test

7/17/2011Setac Testing Framework 18

Page 19: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Setac APIs• Follows widely used style for unit testing

o Integrated with Junito Refined over time based on examples

• Checking assertions when system is stable

• Total and partial order of schedule messages

• Status of Test messageso Processed, delivered, etc.

• Status of actorso Mail box: Number of messages, content of mail box, etc.o Execution Status: Blocked, Running, Suspended

7/17/2011Setac Testing Framework 19

Page 20: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Limitations• Handling non-stable systems

o receiveWithin, reactWithin, etc. in a loopo Use assertAfter API in Setac

• Managing anonymous actorso E.g., Futures

• Handling actors whose source code is not available

7/17/2011Setac Testing Framework 20

Page 21: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Future Work• Integrate Setac with Scala actor library

o To eliminate the required change in the program under testo To remove some of its limitations

• Extend the solution for Akka actors

• Integrate with ScalaTest

• Evaluate Setac on larger number of exampleso Speed, expressiveness

7/17/2011Setac Testing Framework 21

Page 22: Setac: A Phased Deterministic Testing Framework for Scala Actorsdays2011.scala-lang.org/sites/days2011/files/03. Setac.pdf · 2011-09-20 · Actors in Scala • Package scala.actors

Conclusions• Large number of schedules in actor programs

o Only some schedules might be important to test

• It is non-trivial to force specific schedule and check assertions at appropriate timeso Sleeps - unreliableo Latches – hard to write/reado Changes in the program under test- high cost

• Setaco Reliableo Easy to writeo Very minimal changes in the program under test

• Open for collaborationo Please try it: http://mir.cs.illinois.edu/setac/

7/17/2011Setac Testing Framework 22