05.03.2016 Views

Programming in Scala”

fpiscompanion

fpiscompanion

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Chapter notes 22<br />

forAll(Gen.listOf(Gen.choose(1,10))) { l =><br />

val buf = new collection.mutable.ArrayStack[Int]<br />

val beforeSize = buf.size<br />

l.foreach(buf.push)<br />

buf.beforeSize == 0 && buf.size == l.size<br />

}<br />

In this case, the “<strong>in</strong>terpreter” is the push method on ArrayStack, which modifies the stack <strong>in</strong> place,<br />

and the “<strong>in</strong>structions” are simply the <strong>in</strong>tegers from the <strong>in</strong>put list. But the basic idea can be extended<br />

to test<strong>in</strong>g richer <strong>in</strong>terfaces–for <strong>in</strong>stance, we could generate <strong>in</strong>structions that could either push or pop<br />

elements from an ArrayStack (perhaps represented as a List[Option[Int]]), and write a property<br />

that sequences of push and pop preserve the <strong>in</strong>variants of ArrayStack (for <strong>in</strong>stance, the f<strong>in</strong>al size<br />

of the stack should be the number of push calls m<strong>in</strong>us the number of pop calls). Care must be<br />

taken to craft generators that produce valid sequences of <strong>in</strong>structions (for <strong>in</strong>stance, pop without a<br />

correspond<strong>in</strong>g prior push is not a valid <strong>in</strong>put).<br />

Similar ideas have been used for test<strong>in</strong>g thread safety of concurrent programs. (See F<strong>in</strong>d<strong>in</strong>g Race<br />

Conditions <strong>in</strong> Erlang with QuickCheck and PULSE⁹⁹ (PDF)) The key <strong>in</strong>sight here is that threadsafe<br />

code does not allow the nondeterm<strong>in</strong>ism of thread schedul<strong>in</strong>g to be observable. That is, for<br />

any partial order of <strong>in</strong>structions run concurrently, we ought to able to f<strong>in</strong>d some s<strong>in</strong>gle-threaded<br />

l<strong>in</strong>ear sequence of these <strong>in</strong>structions with the same observable behavior (this criteria is often called<br />

l<strong>in</strong>earizability). For <strong>in</strong>stance, if our ArrayStack were thread-safe, we would expect that if 2 push<br />

operations were performed sequentially, followed by two pop operations and two push operations<br />

performed concurrently, this should yield the same result as some determ<strong>in</strong>istic l<strong>in</strong>ear sequence of<br />

these push and pop operations). There are some subtleties and <strong>in</strong>terest<strong>in</strong>g questions about how to<br />

model this and how to report and m<strong>in</strong>imize fail<strong>in</strong>g test cases. In particular, do<strong>in</strong>g it the “obvious” way<br />

ends up be<strong>in</strong>g <strong>in</strong>tractable due to hav<strong>in</strong>g to search through a comb<strong>in</strong>atorial number of <strong>in</strong>terleav<strong>in</strong>gs to<br />

f<strong>in</strong>d one that satisfies the observation. The Erlang paper l<strong>in</strong>ked above has more details, <strong>in</strong> particular<br />

see section 4. You may be <strong>in</strong>terested to explore how to <strong>in</strong>corporate these ideas <strong>in</strong>to the library we<br />

developed, possibly build<strong>in</strong>g on the parallelism library we wrote last chapter.<br />

Lastly, we mention that one design goal of some libraries <strong>in</strong> this style is to avoid hav<strong>in</strong>g to explicitly<br />

construct generators. The QuickCheck library makes use of a Haskell type class to provide <strong>in</strong>stances<br />

of Gen “automatically”, and this idea has also been borrowed by ScalaCheck¹⁰⁰. This can certa<strong>in</strong>ly<br />

be convenient, especially for simple examples, though we often f<strong>in</strong>d that explicit generators are<br />

necessary to capture all the <strong>in</strong>terest<strong>in</strong>g constra<strong>in</strong>ts on the shape or form of the <strong>in</strong>puts to a function.<br />

⁹⁹http://www.protest-project.eu/upload/paper/icfp070-claessen.pdf<br />

¹⁰⁰https://github.com/rickynils/scalacheck/wiki/User-Guide

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!