Modules
Coyote-style controlled concurrency testing for BEAM.
Controller-aware wrappers around :atomics.
Raised when a controlled-concurrency iteration finds a bug. The message includes the iteration number, seed, formatted schedule, and a command for replaying the bug.
Backward-slice a trace to the events causally relevant to a given failing step.
Per-process causal consistency check for register-shaped models.
Decide whether a Lockstep.History is linearizable with respect
to a given Lockstep.Model.
A paired (:invoke, :complete) operation. complete is nil
if the operation is still pending.
Decide whether a Lockstep.History is sequentially consistent
with respect to a Lockstep.Model.
Multi-node simulation under Lockstep's controller.
The scheduler. A GenServer that intercepts every Lockstep sync point
and picks the next process to run per the configured strategy.
Controller-aware wrappers around the most-used :ets operations.
Rewrites Erlang source (.erl) so that vanilla OTP calls
(gen_server:call, erlang:spawn, Pid ! Msg, bare receive)
go through Lockstep's controller. Mirrors Lockstep.Rewriter but
on Erlang's abstract format instead of Elixir's macro AST.
GenServer-shaped wrapper that runs under Lockstep's controller.
Minimal :gen_statem-shaped wrapper that runs under Lockstep's
controller. Supports the handle_event_function callback mode -- one
handle_event/4 clause per (event_type, event_content, state, data)
combination -- which is the pattern most modern Elixir code uses.
Deterministic, seeded streams of operations for Jepsen-style workloads.
Cluster-wide name registry, mirror of Erlang's :global.
Jepsen-style operation history recorder.
One event in the history. Multiple events combine to describe an
operation: an :invoke plus a matching :ok / :fail / :info
on the same process.
Optional Anthropic Claude integration: explains a Lockstep concurrency bug in plain English and suggests a fix.
Compile-time AST scanner that warns when a ctest body uses operations
that aren't routed through Lockstep's controller. Bare send, bare
receive, Process.send_after, GenServer.call, Task.async, and
similar will silently break the controlled schedule -- better to warn
at compile time than have the user wonder why nothing reproduces.
Core file-rewriting logic for the :lockstep_rewrite Mix compiler.
Reads source files, runs them through Lockstep.Rewriter, and writes
the rewritten output to a build directory.
Built-in source-string preprocessors for Lockstep.MixCompiler.compile/1.
A specification of correct sequential behavior for a system under
test. Consistency checkers (Lockstep.Checker.Linearizable,
Lockstep.Checker.SequentialConsistency) consult a Model to
decide whether a candidate serial order of operations is valid.
Single-cell register model: read, write, and compare-and-swap.
Experimental, observational only. Drive unmodified OTP code
under a Lockstep-style runner using :erlang.trace/3 and
:erlang.suspend_process/1. The intent was full PCT-style
scheduling control over arbitrary OTP code; in practice
:erlang.trace is observational, not interventional, and this
module does not reliably force interesting interleavings.
Controller-aware wrappers around :persistent_term.
Controller-aware wrappers for Process.whereis/1, Process.register/2,
Process.unregister/1, and Process.registered/0.
Reads-From Fuzzing — coverage-guided concurrency exploration.
Mirror of Erlang's :rpc module under Lockstep's controlled
scheduling. Cross-node apply/4-style calls are modeled by
spawning a process on the target node, having it execute the
function, and shipping the result back to the caller via a
Lockstep-controlled message.
Lockstep-aware process registry. Models the most common subset of
OTP Registry under Lockstep's controller, so libraries that depend
on key-based process lookup work under controlled scheduling.
Re-run a test body deterministically from a saved Lockstep trace.
Raised by Lockstep.Replay.run/2 when the replayed schedule cannot be
faithfully reproduced from the recorded trace. Almost always means the
user code under test depends on uncontrolled nondeterminism — raw RNG,
system time, ETS interleavings inside non-yielding handlers, NIFs, or
real I/O.
Compile-time AST rewriter that converts vanilla OTP calls into their
Lockstep.* equivalents inside a ctest body. Lets test bodies
read like ordinary Elixir without sacrificing controlled scheduling.
Runs a controlled test body N times. On bug: saves the trace and
raises Lockstep.BugFound with a formatted schedule.
Reduce a failing schedule to a minimal one that still triggers the same bug, deterministically.
Behaviour for scheduling strategies.
PCT for the first K steps, then uniform random walk.
Iterative-Deepening PCT.
Probabilistic Concurrency Testing.
POS (Partial-Order Sampling). On every step, with probability
:resample_prob, re-randomize the priorities of all currently-ready
processes; otherwise keep the current priorities. Then run the
highest-priority enabled process.
Uniform random over the ready set. Cheap, fair, the default baseline.
Re-runs the schedule recorded in a saved trace.
A :one_for_one supervisor that runs under Lockstep's controller.
Builds on Lockstep.spawn_link/1 + Lockstep.flag(:trap_exit, true)
so child crashes are observed via {:EXIT, child, reason} and
restarts can be issued in-band with the rest of the test schedule.
Lockstep-controlled Task.async / Task.await / async_stream style helper.
Lockstep-aware Task.Supervisor shim. Each async/start_child
call spawns a managed Lockstep process; supervisor restart
semantics aren't modeled (use Lockstep.Supervisor for that).
ExUnit case template for controlled concurrency tests.
Recorded schedule. A trace is the sequence of decisions the controller made during a test iteration.
Mix Tasks
Mix compiler that rewrites source files via Lockstep.Rewriter
before the standard Elixir compiler runs.
Dump a saved Lockstep trace as a raw Elixir term. Useful for grepping or feeding into another tool.
Print a saved Lockstep trace as a human-readable schedule, or re-run a specific test function under the recorded schedule.
Reduce a failing Lockstep trace to a minimal schedule that still triggers the same bug.