• Stars
    star
    188
  • Rank 205,563 (Top 5 %)
  • Language
    Haskell
  • Created almost 10 years ago
  • Updated 12 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Systematic concurrency testing meets Haskell.

dejafu

[Déjà Fu is] A martial art in which the user's limbs move in time as well as space, […] It is best described as "the feeling that you have been kicked in the head this way before"

-- Terry Pratchett, Thief of Time

Déjà Fu is a unit-testing library for concurrent Haskell programs. Tests are deterministic and expressive, making it easy and convenient to test your threaded code. Available on GitHub, Hackage, and Stackage.

Features:

  • An abstraction over the concurrency functionality in IO
  • Deterministic testing of nondeterministic code
  • Both complete (slower) and incomplete (faster) modes
  • A unit-testing-like approach to writing test cases
  • A property-testing-like approach to comparing stateful operations
  • Testing of potentially nonterminating programs
  • Integration with HUnit and tasty

There are a few different packages under the Déjà Fu umbrella:

Version Summary
concurrency 1.11.0.3 Typeclasses, functions, and data types for concurrency and STM.
dejafu 2.4.0.5 Systematic testing for Haskell concurrency.
hunit-dejafu 2.0.0.6 Deja Fu support for the HUnit test framework.
tasty-dejafu 2.1.0.0 Deja Fu support for the Tasty test framework.

Each package has its own README and CHANGELOG in its subdirectory.

There is also dejafu-tests, the test suite for dejafu. This is in a separate package due to Cabal being bad with test suite transitive dependencies.

Installation

Install from Hackage globally:

$ cabal install dejafu

Or add it to your cabal file:

build-depends: ...
             , dejafu

Or to your package.yaml:

dependencies:
  ...
  - dejafu

Quick start guide

Déjà Fu supports unit testing, and comes with a helper function called autocheck to look for some common issues. Let's see it in action:

import Control.Concurrent.Classy

myFunction :: MonadConc m => m String
myFunction = do
  var <- newEmptyMVar
  fork (putMVar var "hello")
  fork (putMVar var "world")
  readMVar var

That MonadConc is a typeclass abstraction over concurrency, but we'll get onto that shortly. First, the result of testing:

> autocheck myFunction
[pass] Never Deadlocks
[pass] No Exceptions
[fail] Consistent Result
    "hello" S0----S1--S0--

    "world" S0----S2--S0--
False

There are no deadlocks or uncaught exceptions, which is good; but the program is (as you probably spotted) nondeterministic!

Along with each result, Déjà Fu gives us a representative execution trace in an abbreviated form. Sn means that thread n started executing, and Pn means that thread n pre-empted the previously running thread.

Why Déjà Fu?

Testing concurrent programs is difficult, because in general they are nondeterministic. This leads to people using work-arounds like running their testsuite many thousands of times; or running their testsuite while putting their machine under heavy load.

These approaches are inadequate for a few reasons:

  • How many runs is enough? When you are just hopping to spot a bug by coincidence, how do you know to stop?
  • How do you know if you've fixed a bug you saw previously? Because the scheduler is a black box, you don't know if the previously buggy schedule has been re-run.
  • You won't get that much scheduling variety! Operating systems and language runtimes like to run threads for long periods of time, which reduces the variety you get (and so drives up the number of runs you need).

Déjà Fu addresses these points by offering complete testing. You can run a test case and be guaranteed to find all results with some bounds. These bounds can be configured, or even disabled! The underlying approach used is smarter than merely trying all possible executions, and will in general explore the state-space quickly.

If your test case is just too big for complete testing, there is also a random scheduling mode, which is necessarily incomplete. However, Déjà Fu will tend to produce much more schedule variety than just running your test case in IO the same number of times, and so bugs will tend to crop up sooner. Furthermore, as you get execution traces out, you can be certain that a bug has been fixed by simply following the trace by eye.

Contributing

See the "contributing" page on the website.

If you'd like to get involved with Déjà Fu, check out the "good first issue" label on the issue tracker.

Release notes

See the CHANGELOG.markdown file.

Questions, feedback, discussion

  • For general help talk to me in IRC (barrucadu in #haskell) or shoot me an email ([email protected])
  • For bugs, issues, or requests, please file an issue.

Bibliography

These libraries wouldn't be possible without prior research, which I mention in the documentation. Haddock comments get the full citation, whereas in-line comments just get the shortened name:

There are also a couple of papers on dejafu itself:

More Repositories

1

markov

Markov chain text generator, as used for KingJamesProgramming
Python
452
star
2

nixfiles

My NixOS configuration and assorted other crap.
Nix
135
star
3

hledger-scripts

Helpful scripts to do things with your hledger data.
Haskell
54
star
4

lainonlife

RIP lainchan radio, taken out by HDD failure.
Python
53
star
5

logdb

An efficient log-structured database supporting efficient insertion of new entries and removal from either end of the log.
Go
28
star
6

finances

A small tool to visualise my hledger journal. Your mileage may vary.
JavaScript
27
star
7

bookdb

Python
25
star
8

dotfiles

My dotfiles and assorted other crap, managed with chezmoi.
Python
25
star
9

resolved

A simple DNS server for home networks.
Rust
20
star
10

irc-client

This project is essentially abandonware!
Haskell
20
star
11

cv

My CV
TeX
19
star
12

minifu

A tutorial on writing a concurrency testing tool in Haskell
Haskell
13
star
13

bible

The King James Bible, typeset with LaTeX
TeX
12
star
14

irc-conduit

This project is essentially abandonware!
Haskell
11
star
15

yukibot

An IRC bot, and associated libraries, for the ##compsoc-uk-anime channel on Freenode
Haskell
10
star
16

meng-project

MEng project on verified garbage collection
TeX
8
star
17

quickie

A quick brainfuck compiler / JITed interpreter.
Haskell
6
star
18

bookmarks

A little search engine to manage my bookmarks
Python
5
star
19

memo.barrucadu.co.uk

My memos
Haskell
5
star
20

irc-ctcp

This project is essentially abandonware!
Haskell
4
star
21

coco

The Concurrency Commentator; giving you cheap remarks about concurrent programs.
Haskell
4
star
22

cabal-info

Read information from cabal files.
Haskell
4
star
23

search-party

A library for parallel, non-deterministic, search.
Haskell
4
star
24

pusher-ws

Implementation of the Pusher WebSocket protocol in Haskell
Haskell
3
star
25

aoc

Advent of Code
Haskell
3
star
26

bfo

Optimising brainfuck interpreter.
Rust
3
star
27

quantified-self-scripts

Grabbing data about me and pushing it into a dashboard
Python
3
star
28

barrucadu.co.uk

My personal website
HTML
2
star
29

prometheus-speedtest-exporter

Python
2
star
30

prometheus-awair-exporter

Go
2
star
31

barrucadu.dev

2
star
32

both

This project is essentially abandonware!
Haskell
2
star
33

phd

I have no idea what I'm doing
TeX
2
star
34

monad-monitor

Haskell
2
star
35

alphagov-backend.hs

Drop-in replacements for GOV.UK backend services, written in Haskell using servant.
Haskell
1
star
36

rogue-mayor

A town management game I'll probably never finish.
Rust
1
star
37

lambdamoo

C
1
star
38

king-james-programming

Markov chain text generator, as used for KingJamesProgramming (post-2024)
Shell
1
star
39

sat

Rust
1
star
40

packdeps-github

Open issues on GitHub about outdated dependencies automatically
Haskell
1
star
41

govuk-rota-generators

Generates rotas for GOV.UK teams.
Python
1
star
42

sed-as-a-service

An innovative solution to turn CPU-bound sed invocations into IO-bound network requests
Java
1
star