|
ravel
Deterministic simulation testing for C++. Seed a bug, replay it exact.
|
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.
>Unreleased
Seeds, choice lists and the C ABI are unchanged from 0.3.0: no behavior change apart from the shrinking fix below.
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.RAVEL_COVERAGE and a CI job that builds with coverage, runs the tests and uploads an HTML report.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).warnings (GCC and Clang) and static-analysis (clang-tidy on the library, cppcheck).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/, CMake option RAVEL_BUILD_FUZZ, RAVEL_FUZZ for libFuzzer), a fuzz smoke job in CI and a manual long-run workflow.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.uint64_t to size_t conversions were unchecked.-fcoroutines for it, which <coroutine> needs there.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.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.tools/check_docs.py).///), so the API reference shows the descriptions. No behavior change: seeds and choice lists from 0.2.0 still mean the same runs.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.ShrinkOptions::threads.find_package(ravel)); a Conan recipe and a vcpkg overlay port.ravel_soak) that checks ravel's own replay promises over many seeds.NotFound instead of an empty result.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.