Antithesis' Test Composer drives Jepsen by calling shell scripts, which communicate with the test via a control directory full of FIFOs. Each FIFO represents a single test composer action. They work like this:
The types of commands are:
op-123: Runs a single operation from the generatorcheck: Wraps up the test's :generator, runs :final-generator, and
checks the history.This namespace provides the Jepsen-side infrastructure for watching the FIFO
directory, a test runner like jepsen.core/run!, and a CLI command called
antithesis which works like test, but uses our runner instead.
Antithesis' Test Composer drives Jepsen by calling shell scripts, which
communicate with the test via a control directory full of FIFOs. Each FIFO
represents a single test composer action. They work like this:
1. Test composer calls a script to do something.
2. Script creates a fifo like /run/jepsen/op-1234, and blocks on it.
3. Jepsen, watching /run/jepsen, detects the new fifo
4. Jepsen fires off an invocation
5. The operation completes
6. Jepsen writes the results of the operation to /run/jepsen/invoke_1234
7. Jepsen closes the FIFO
8. The shell script prints the results out and exits
9. The test composer receives the results
The types of commands are:
- `op-123`: Runs a single operation from the generator
- `check`: Wraps up the test's :generator, runs :final-generator, and
checks the history.
This namespace provides the Jepsen-side infrastructure for watching the FIFO
directory, a test runner like `jepsen.core/run!`, and a CLI command called
`antithesis` which works like `test`, but uses our runner instead.(antithesis-cmd opts)A command package for jepsen.cli. Provides a new command, lein run antithesis, which works like lein run test, but uses the Antithesis test
composer to drive execution. Options:
{:opt-spec A vector of additional options for tools.cli. Merge into
test-opt-spec. Optional.
:opt-fn A function which transforms parsed options. Composed after
test-opt-fn. Optional.
:opt-fn* Replaces test-opt-fn, in case you want to override it
altogether.
:usage Defaults to jc/test-usage. Optional.
:test-fn A function that receives the option map and constructs a test.}
A command package for jepsen.cli. Provides a new command, `lein run
antithesis`, which works like `lein run test`, but uses the Antithesis test
composer to drive execution. Options:
{:opt-spec A vector of additional options for tools.cli. Merge into
`test-opt-spec`. Optional.
:opt-fn A function which transforms parsed options. Composed after
`test-opt-fn`. Optional.
:opt-fn* Replaces test-opt-fn, in case you want to override it
altogether.
:usage Defaults to `jc/test-usage`. Optional.
:test-fn A function that receives the option map and constructs a test.}(complete-fifo-op! this status out)Completes this operation with the given exit status (ignored) and stdout, which is printed to the FIFO.
Completes this operation with the given exit status (ignored) and stdout, which is printed to the FIFO.
The directory where we watch for fifo operations.
The directory where we watch for fifo operations.
(fifo-queue)Constructs a queue full of pending FIFO operations. The fifo watcher writes to this queue, and the interpreter reads from it, completing its promises.
Constructs a queue full of pending FIFO operations. The fifo watcher writes to this queue, and the interpreter reads from it, completing its promises.
(fifo-watcher! test)Takes a test, and launches a future which watches the FIFO directory for new
files. Each new file results in a FifoOp delivered to (:fifo-queue test).
Creates the directory if it does not exist. Always empties directory before
watching.
Takes a test, and launches a future which watches the FIFO directory for new files. Each new file results in a FifoOp delivered to `(:fifo-queue test)`. Creates the directory if it does not exist. Always empties directory before watching.
(interpret! test)Borrowed from jepsen.generator.interpreter, with adaptations for our FIFO queue. Notably, the test now contains a :fifo-queue, which delivers InterpreterMsgs to the interpreter thread. These messages are of two types:
:op Perform a single operation from the (presumably main phase) of the generator. Delivers the [invoke, complete] pair to the message's promise when done.
:check Enters the final phase of the generator. Flips test-phase to :final, and consumes generator operations as quickly as possible to perform the final phase. When these operations are exhausted, the interpreter returns, triggering the final analysis.
Takes a test with a :store :handle open. Causes the test's reference to the :generator to be forgotten, to avoid retaining the head of infinite seqs. Opens a writer for the test's history using that handle. Creates an initial context from test and evaluates all ops from (:gen test). Spawns a thread for each worker, and hands those workers operations from gen; each thread applies the operation using (:client test) or (:nemesis test), as appropriate. Invocations and completions are journaled to a history on disk. Returns a new test with no :generator and a completed :history.
Generators are automatically wrapped in friendly-exception and validate. Clients are wrapped in a validator as well.
Automatically initializes the generator system, which, on first invocation, extends the Generator protocol over some dynamic classes like (promise).
Borrowed from jepsen.generator.interpreter, with adaptations for our FIFO
queue. Notably, the test now contains a :fifo-queue, which delivers
InterpreterMsgs to the interpreter thread. These messages are of two types:
:op Perform a single operation from the (presumably main phase) of the
generator. Delivers the [invoke, complete] pair to the message's
promise when done.
:check Enters the final phase of the generator. Flips test-phase to
:final, and consumes generator operations as quickly as possible
to perform the final phase. When these operations are exhausted,
the interpreter returns, triggering the final analysis.
Takes a test with a :store :handle open. Causes the test's reference to the
:generator to be forgotten, to avoid retaining the head of infinite seqs.
Opens a writer for the test's history using that handle. Creates an initial
context from test and evaluates all ops from (:gen test). Spawns a thread for
each worker, and hands those workers operations from gen; each thread applies
the operation using (:client test) or (:nemesis test), as appropriate.
Invocations and completions are journaled to a history on disk. Returns a new
test with no :generator and a completed :history.
Generators are automatically wrapped in friendly-exception and validate.
Clients are wrapped in a validator as well.
Automatically initializes the generator system, which, on first invocation,
extends the Generator protocol over some dynamic classes like (promise).(main-gen gen)We need a way to terminate the regular generator and move to the final generator. However, the regular generator and final generator may be wrapped in some kind of state-tracking generator which allows context to pass from one to the other--and we don't have a way to reach inside that single generator and trigger a flip.
This generator is intended to be called by the test author, and wraps the
main phase generator. It uses an atom, stored in the test: :antithesis-phase.
This generator emits operations so long as the phase :main. Otherwise it
emits nil, which forces any composed generator using this to proceed to the
next phase--presumably, the final generator before checking.
In non-antithesis environments, this wrapper has no effect.
We need a way to terminate the regular generator and move to the final generator. However, the regular generator and final generator may be *wrapped* in some kind of state-tracking generator which allows context to pass from one to the other--and we don't have a way to reach inside that single generator and trigger a flip. This generator is intended to be called by the test author, and wraps the main phase generator. It uses an atom, stored in the test: :antithesis-phase. This generator emits operations so long as the phase `:main`. Otherwise it emits `nil`, which forces any composed generator using this to proceed to the next phase--presumably, the final generator before checking. In non-antithesis environments, this wrapper has no effect.
(notify-test-checked! test antithesis-phase)Complets the final check fifo op once the test is complete. Returns test unchanged.
Complets the final check fifo op once the test is complete. Returns test unchanged.
(run! test)Runs a test, taking direction from fifo-watcher. See jepsen.core/run!
Runs a test, taking direction from fifo-watcher. See jepsen.core/run!
(run-case! test)Takes a test with a store handle. Spawns nemesis and clients, runs the generator, and returns test with no :generator and a completed :history.
Takes a test with a store handle. Spawns nemesis and clients, runs the generator, and returns test with no :generator and a completed :history.
(with-fifo-watcher! test & body)Opens a fifo watcher for the duration of the body, and terminates it when the body completes.
Opens a fifo watcher for the duration of the body, and terminates it when the body completes.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |