Struct ctest2::TestGenerator

source ·
pub struct TestGenerator { /* private fields */ }
Expand description

A builder used to generate a test suite.

This builder has a number of configuration options which modify how the generated tests are emitted, and it is also the main entry point for parsing an FFI header crate for definitions.

Implementations§

source§

impl TestGenerator

source

pub fn new() -> Self

Creates a new blank test generator.

This won’t actually be that useful until functions like header are called, but the main “finalization method” is the generate method.

source

pub fn header(&mut self, header: &str) -> &mut Self

Add a header to be included as part of the generated C file.

The generate C test will be compiled by a C compiler, and this can be used to ensure that all the necessary header files are included to test all FFI definitions.

§Examples
use std::env;
use std::path::PathBuf;

use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.header("foo.h")
   .header("bar.h");
source

pub fn rust_version(&mut self, major: u64, minor: u64, patch: u64) -> &mut Self

Target Rust version: major.minor.patch

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.rust_version(1, 0, 1);
source

pub fn include<P: AsRef<Path>>(&mut self, p: P) -> &mut Self

Add a path to the C compiler header lookup path.

This is useful for if the C library is installed to a nonstandard location to ensure that compiling the C file succeeds.

§Examples
use std::env;
use std::path::PathBuf;

use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
cfg.include(out_dir.join("include"));
source

pub fn language(&mut self, lang: Lang) -> &mut Self

Sets the programming language.

§Examples
use std::env;
use std::path::PathBuf;

use ctest2::{TestGenerator, Lang};

let mut cfg = TestGenerator::new();
cfg.language(Lang::CXX);
source

pub fn flag(&mut self, flag: &str) -> &mut Self

Add a flag to the C compiler invocation.

This can be useful for tweaking the warning settings of the underlying compiler.

§Examples
use std::env;
use std::path::PathBuf;

use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();

// if msvc
cfg.flag("/wd4820");

// if gnu
cfg.flag("-Wno-type-limits");
source

pub fn out_dir<P: AsRef<Path>>(&mut self, p: P) -> &mut Self

Configures the output directory of the generated Rust and C code.

Note that for Cargo builds this defaults to $OUT_DIR and it’s not necessary to call.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.out_dir("path/to/output");
source

pub fn target(&mut self, target: &str) -> &mut Self

Configures the target to compile C code for.

Note that for Cargo builds this defaults to $TARGET and it’s not necessary to call.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.target("x86_64-unknown-linux-gnu");
source

pub fn define(&mut self, k: &str, v: Option<&str>) -> &mut Self

Set a -D flag for the C compiler being called.

This can be used to define various variables to configure how header files are included or what APIs are exposed from header files.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.define("_GNU_SOURCE", None)
   .define("_WIN32_WINNT", Some("0x8000"));
source

pub fn cfg(&mut self, k: &str, v: Option<&str>) -> &mut Self

Set a --cfg option with which to expand the Rust FFI crate.

By default the Rust code is run through expansion to determine what C APIs are exposed (to allow differences across platforms).

The k argument is the #[cfg] value to define, while v is the optional value of v:

  • k == "foo" and v == None makes #[cfg(foo)] expand. That is, cfg!(foo) expands to true.

  • k == "bar" and v == Some("baz") makes #[cfg(bar = "baz")] expand. That is, cfg!(bar = "baz") expands to true.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.cfg("foo", None) // cfg!(foo)
   .cfg("bar", Some("baz")); // cfg!(bar = "baz")
source

pub fn verbose_skip(&mut self, v: bool) -> &mut Self

Skipped item names are printed to stderr if v is true.

source

pub fn type_name<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str, bool, bool) -> String + 'static,

Configures how a Rust type name is translated to a C type name.

The closure is given a Rust type name as well as a boolean indicating whether it’s a struct or not.

The default behavior is that struct foo in Rust is translated to struct foo in C, and type foo in Rust is translated to foo in C. Some header files, however, have the convention that struct foo_t in Rust should be foo_t in C, for example.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.type_name(|ty, is_struct, is_union| {
    if is_struct {
        format!("{}_t", ty)
    } else {
        ty.to_string()
    }
});
source

pub fn field_name<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str, &str) -> String + 'static,

Configures how a Rust struct field is translated to a C struct field.

The closure is given a Rust struct name as well as a field within that struct. The name of the corresponding field in C is then returned.

By default the field name in C just matches the field name in Rust, but this is useful for fields which otherwise are named after keywords in Rust (such as a field name of type).

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.field_name(|_s, field| {
    field.replace("foo", "bar")
});
source

pub fn volatile_item<F>(&mut self, f: F) -> &mut Self
where F: Fn(VolatileItemKind) -> bool + 'static,

Is volatile?

The closure given takes a VolatileKind denoting a particular item that could be volatile, and returns whether this is the case.

§Examples
use ctest2::{TestGenerator, VolatileItemKind::StructField};

let mut cfg = TestGenerator::new();
cfg.volatile_item(|i| {
    match i {
        StructField(ref s, ref f)
            if s == "foo_struct" && f == "foo_field"
             => true,
        _ => false,
}});
source

pub fn array_arg<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str, usize) -> bool + 'static,

Is argument of function an array?

The closure denotes whether particular argument of a function is an array.

§Examples
use ctest2::{TestGenerator};

let mut cfg = TestGenerator::new();
cfg.array_arg(|i, n| {
    match (i, n) {
        ("foo", 0) => true,
        _ => false,
}});
source

pub fn const_cname<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str) -> String + 'static,

Configures how Rust consts names are translated to C.

The closure is given a Rust const name. The name of the corresponding const in C is then returned.

By default the const name in C just matches the const name in Rust.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.const_cname(|c| {
    c.replace("FOO", "foo")
});
source

pub fn skip_field<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str, &str) -> bool + 'static,

Configures whether all tests for a field are skipped or not.

The closure is given a Rust struct name as well as a field within that struct. A flag indicating whether the field should be tested for type, size, offset, and alignment should be skipped or not.

By default all field properties are tested.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.skip_field(|s, field| {
    s == "foo_t" || (s == "bar_t" && field == "bar")
});
source

pub fn skip_field_type<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str, &str) -> bool + 'static,

Configures whether tests for the type of a field is skipped or not.

The closure is given a Rust struct name as well as a field within that struct. A flag indicating whether the field’s type should be tested is returned.

By default all field properties are tested.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.skip_field_type(|s, field| {
    s == "foo_t" || (s == "bar_t" && field == "bar")
});
source

pub fn skip_signededness<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str) -> bool + 'static,

Configures whether a types signededness is tested or not.

The closure is given the name of a Rust type, and returns whether the type should be tested as having the right sign (positive or negative).

By default all signededness checks are performed.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.skip_signededness(|s| {
    s.starts_with("foo_")
});
source

pub fn skip_fn<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str) -> bool + 'static,

Configures whether tests for a function definition are generated.

The closure is given the name of a Rust FFI function and returns whether test will be generated.

By default, a function’s signature is checked along with its address in memory.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.skip_fn(|s| {
    s.starts_with("foo_")
});
source

pub fn skip_static<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str) -> bool + 'static,

Configures whether tests for a static definition are generated.

The closure is given the name of a Rust extern static definition and returns whether test will be generated.

By default, a static’s type is checked along with its address in memory.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.skip_static(|s| {
    s.starts_with("foo_")
});
source

pub fn skip_fn_ptrcheck<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str) -> bool + 'static,

Configures whether tests for a function pointer’s value are generated.

The closure is given the name of a Rust FFI function and returns whether the test will be generated.

By default generated tests will ensure that the function pointer in C corresponds to the same function pointer in Rust. This can often uncover subtle symbol naming issues where a header file is referenced through the C identifier foo but the underlying symbol is mapped to something like __foo_compat.

source

pub fn skip_const<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str) -> bool + 'static,

Configures whether the tests for a constant’s value are generated.

The closure is given the name of a Rust constant and returns whether the test will be generated.

By default all constant values are verified.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.skip_const(|s| {
    s.starts_with("FOO_")
});
source

pub fn skip_type<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str) -> bool + 'static,

Configures whether the tests for a typedef are emitted.

The closure is passed the name of a Rust typedef and returns whether the tests are generated.

By default existence of a typedef is checked.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.skip_type(|s| {
    s.starts_with("foo_")
});
source

pub fn skip_struct<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str) -> bool + 'static,

Configures whether the tests for a struct are emitted.

The closure is passed the name of a Rust struct and returns whether the tests are generated.

By default structs undergo tests such as size, alignment, existence, field offset, etc.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.skip_struct(|s| {
    s.starts_with("foo_")
});
source

pub fn skip_roundtrip<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str) -> bool + 'static,

Configures whether the ABI roundtrip tests for a type are emitted.

The closure is passed the name of a Rust type and returns whether the tests are generated.

By default all types undergo ABI roundtrip tests. Arrays cannot undergo an ABI roundtrip because they cannot be returned by C functions, and have to be manually skipped here.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.skip_roundtrip(|s| {
    s.starts_with("foo_")
});
source

pub fn fn_cname<F>(&mut self, f: F) -> &mut Self
where F: Fn(&str, Option<&str>) -> String + 'static,

Configures the name of a function in the generate C code.

The closure is passed the Rust name of a function as well as any optional #[link_name] specified.

By default the name of the generated C reference is the same as the Rust function. This is useful, however, if different naming conventions are used in Rust than are present in C (which is discouraged, however).

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.fn_cname(|rust, link_name| link_name.unwrap_or(rust).to_string());
source

pub fn generate<P: AsRef<Path>>(&mut self, krate: P, out_file: &str)

Generate all tests.

This function is first given the path to the *-sys crate which is being tested along with an output file from where to generate the Rust side of the tests.

This function does not consume the builder, but it is expected that all configuration has happened prior to calling this function.

This will also generate the corresponding C side of the tests and compile it.

§Examples
use ctest2::TestGenerator;

let mut cfg = TestGenerator::new();
cfg.generate("../path/to/libfoo-sys/lib.rs", "all.rs");

Trait Implementations§

source§

impl Default for TestGenerator

source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.