10 releases

new 0.4.8 Feb 17, 2024
0.4.7 Jun 10, 2023
0.4.6 May 6, 2023
0.4.5 Nov 19, 2022
0.3.0 Jun 1, 2020

#48 in Testing

Download history 3495/week @ 2023-10-31 3209/week @ 2023-11-07 3158/week @ 2023-11-14 2290/week @ 2023-11-21 3637/week @ 2023-11-28 3263/week @ 2023-12-05 3928/week @ 2023-12-12 3463/week @ 2023-12-19 2333/week @ 2023-12-26 5650/week @ 2024-01-02 5696/week @ 2024-01-09 5045/week @ 2024-01-16 5001/week @ 2024-01-23 4578/week @ 2024-01-30 3193/week @ 2024-02-06 3783/week @ 2024-02-13

17,315 downloads per month
Used in libc-test





Note: This is a fork of ctest, intended as a temporary replacement until maintenance of ctest resumes.

Automated testing of FFI bindings in Rust. This repository is intended to validate the *-sys crates that can be found on crates.io to ensure that the APIs in Rust match the APIs defined in C.

MSRV (Minimum Supported Rust Version)

The MSRV is 1.56.0 because of the transitive dependencies. Note that MSRV may be changed anytime by dependencies.


Unfortunately the usage today is a little wonky, but to use this library, first, create a new Cargo project in your repo:

$ cargo new --bin systest

Then, edit systest/Cargo.toml to add these dependencies:

# ...
build = "build.rs"

mylib-sys = { path = "../mylib-sys" }
libc = "0.2"

ctest2 = "0.4"

Next, add a build script to systest/build.rs:

fn main() {
    let mut cfg = ctest2::TestGenerator::new();

    // Include the header files where the C APIs are defined

    // Include the directory where the header files are defined

    // Generate the tests, passing the path to the `*-sys` library as well as
    // the module to generate.
    cfg.generate("../mylib-sys/lib.rs", "all.rs");

Next, add this to src/main.rs


use libc::*;
use mylib_sys::*;

include!(concat!(env!("OUT_DIR"), "/all.rs"));

And you're good to go! To run the tests execute cargo run in the systest directory, and everything should be kicked into action!

How it works

This library will parse the *-sys crate to learn about all extern fn definitions within. It will then generate a test suite to ensure that all function function signatures, constant values, struct layout/alignment, type size/alignment, etc, all match their C equivalent.

The generated tests come in two forms. One is a Rust file which contains the main function (hence the include! above), and another is a C file which is compiled as part of the build script. The C file is what includes all headers and returns information about the C side of things (which is validated in Rust).

A large amount of configuration can be applied to how the C file is generated, you can browse the documentation.

Projects using ctest2


This project is licensed under either of

at your option.


Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in ctest2 by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.


~81K SLoC