API Reference Lockstep v#0.1.0

Copy Markdown View Source

Modules

Coyote-style controlled concurrency testing for BEAM.

Controller-aware Agent -- mirrors the OTP Agent API but every get/update/cast/get_and_update is a Lockstep.GenServer.call (or cast) and therefore a sync point.

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.

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.