ravel
Deterministic simulation testing for C++. Seed a bug, replay it exact.
Loading...
Searching...
No Matches
Changelog

All notable changes to ravel are recorded here. The format follows Keep a Changelog, and versions follow Semantic Versioning with one caveat: before 1.0, a minor version may break the API, the meaning of a seed, and the C ABI. Each such break is listed under "Changed" or "Removed" in the release that makes it.

<a href="https://github.com/FelixMiddelhoff/ravel/compare/v0.4.0...HEAD"

>Unreleased

<a href="https://github.com/FelixMiddelhoff/ravel/compare/v0.3.0...v0.4.0" >0.4.0</a> - 2026-09-20

Seeds, choice lists and the C ABI are unchanged from 0.3.0: no behavior change apart from the shrinking fix below.

Added

  • NuGet package Ravel.Dst for Visual Studio C++ projects (x64, static library with the dynamic MSVC runtime, Release and Debug), built by packaging/nuget/pack.ps1. Not on nuget.org yet; it is attached to each GitHub release.
  • release.yml: pushing a vX.Y.Z tag checks the version everywhere, the CHANGELOG entry and a green soak run on that commit, tests on three systems, packs and tests the NuGet package, and creates the GitHub release.
  • CMake option RAVEL_COVERAGE and a CI job that builds with coverage, runs the tests and uploads an HTML report.
  • CMake option RAVEL_WERROR (warnings as errors, used in CI). Every target now builds with -Wall -Wextra -Wpedantic -Wconversion -Wshadow (MSVC /W4), not only the library.
  • tools/mutation.sh and mull.yml: mutation testing of the library with Mull (Clang).
  • CI jobs warnings (GCC and Clang) and static-analysis (clang-tidy on the library, cppcheck).
  • CI job compilers: GCC 10, 11 and 14, Clang 14, 15 and 19, and a 32-bit GCC 13 build. The README now lists exactly what is tested.
  • Fuzz targets for the choice-list parser and the sweep command line (fuzz/, CMake option RAVEL_BUILD_FUZZ, RAVEL_FUZZ for libFuzzer), a fuzz smoke job in CI and a manual long-run workflow.
  • Documentation: docs/disk-model.md (the exact rules of the virtual disk, and how the model is tested against a reference implementation) and docs/known-limitations.md.
  • Property tests, a disk reference-model differential test, thread-pool stress tests, and a coverage floor in CI (97% lines, 92% branches). The soak workflow also runs ThreadSanitizer and ASan/UBSan variants.

Fixed

  • The library, the tests and the examples now build without warnings on 32-bit targets: several uint64_t to size_t conversions were unchecked.
  • GCC 10 builds: CMake adds -fcoroutines for it, which <coroutine> needs there.
  • The Conan recipe and the vcpkg port no longer try to build the fuzz targets.
  • tools/ravel_trace.py crashed with a Python traceback on some damaged trace files (invalid UTF-8, a header or event that is not a JSON object, an event with a missing or wrongly typed field, absurdly deep nesting). It now reports each with exit status 2. Found by tools/fuzz_trace.py, which is also a unit test.
  • shrink (and so run_seeds with shrink_first_failure, and --replay) could not minimize a run that threw after making random choices: the choices were lost and shrinking failed with "the setup is not deterministic". The choices made before the throw are now kept. Found by the new thread-pool stress tests.

<a href="https://github.com/FelixMiddelhoff/ravel/compare/v0.2.0...v0.3.0" >0.3.0</a> - 2026-09-19

Added

  • ravel::run_sweep_main and ravel::run_sweep: a ready-made command line for simulation test programs (--seeds, --first-seed, --threads, --trace-dir, --no-shrink, --time-limit, --replay FILE, --check-determinism), with exit statuses for CI and error annotations on GitHub Actions.
  • ravel::check_determinism: runs each seed twice and once more replayed from its choices, and names the first step where the runs differ.
  • Simulation::describe(event) and TraceEvent::operator==.
  • tools/ravel_trace.py: summary, show, timeline and diff for trace files.
  • Documentation: a tutorial, a porting guide, a debugging guide, a concepts page, a CI guide, a key-value store walkthrough, a comparison with related tools, and a troubleshooting guide. Every code and output block is generated from real programs, and every error message quoted is looked up in the source, both checked in CI (tools/check_docs.py).
  • The API reference is published to GitHub Pages.

Changed

  • Public headers use Doxygen doc comments (///), so the API reference shows the descriptions. No behavior change: seeds and choice lists from 0.2.0 still mean the same runs.

<a href="https://github.com/FelixMiddelhoff/ravel/compare/v0.1.0...v0.2.0" >0.2.0</a> - 2026-09-19

Added

  • Directories and rename for the virtual disk: rename, remove, sync_dir and list. Directory changes are durable only when synced, and a crash keeps some in-order prefix of the pending ones. Disk::crash_count() lets a task notice that a crash killed it.
  • Channel::receive_within (receive with a timeout), Channel::clear_inbox, and SimulationOptions::time_limit for systems that never go quiet.
  • Shrinking replays candidates in parallel (the result does not depend on the thread count) and has a new pass that lowers two choices together or moves value between them. ShrinkOptions::threads.
  • A working Raft example (leader election, log replication, state persisted through the virtual disk, crashing nodes) with three deliberate bugs that ravel finds.
  • Install rules and a CMake package (find_package(ravel)); a Conan recipe and a vcpkg overlay port.
  • A soak test (ravel_soak) that checks ravel's own replay promises over many seeds.
  • A single-thread guard: using a running simulation from another thread throws.

Changed

  • Reading a missing file returns NotFound instead of an empty result.
  • A disk crash now also decides which pending directory changes survive. Seeds and choice lists from 0.1.0 no longer mean the same runs.
  • The Raft example replaces the quorum-register example.

Fixed

  • shrink() checked that a failure was reproducible using default options instead of the run's own (for example, without its time limit).
  • ravel_simulation_create could let an exception escape the C boundary.

<a href="https://github.com/FelixMiddelhoff/ravel/releases/tag/v0.1.0" >0.1.0</a> - 2026-09-19

Added

  • The first release: a C++20 coroutine scheduler with seeded interleaving and virtual time, virtual channels with loss, latency and reordering, virtual disks with crashes and torn writes, a parallel multi-seed runner, choice-stream shrinking with replayable reproducers, JSON Lines traces, and a small C ABI.